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"}), center0 = null;
 
2002   function mousedowned() {
 
2004         target = d3.event.target,
 
2005         dispatch = event.of(that, arguments),
 
2007         subject = d3.select(d3_window(that)).on(mousemove, moved).on(mouseup, ended),
 
2008         location0 = location(d3.mouse(that)),
 
2009         dragRestore = d3_event_dragSuppress(that);
 
2011     d3_selection_interrupt.call(that);
 
2012     zoomstarted(dispatch);
 
2016       translateTo(d3.mouse(that), location0);
 
2021       subject.on(mousemove, null).on(mouseup, null);
 
2022       dragRestore(dragged && d3.event.target === target);
 
2023       zoomended(dispatch);
 
2027   // These closures persist for as long as at least one touch is active.
 
2028   function touchstarted() {
 
2030         dispatch = event.of(that, arguments),
 
2031         locations0 = {}, // touchstart locations
 
2032         distance0 = 0, // distance² between initial touches
 
2033         scale0, // scale when we started touching
 
2034         zoomName = ".zoom-" + d3.event.changedTouches[0].identifier,
 
2035         touchmove = "touchmove" + zoomName,
 
2036         touchend = "touchend" + zoomName,
 
2038         subject = d3.select(that),
 
2039         dragRestore = d3_event_dragSuppress(that);
 
2042     zoomstarted(dispatch);
 
2044     // Workaround for Chrome issue 412723: the touchstart listener must be set
 
2045     // after the touchmove listener.
 
2046     subject.on(mousedown, null).on(touchstart, started); // prevent duplicate events
 
2048     // Updates locations of any touches in locations0.
 
2049     function relocate() {
 
2050       var touches = d3.touches(that);
 
2052       touches.forEach(function(t) {
 
2053         if (t.identifier in locations0) locations0[t.identifier] = location(t);
 
2058     // Temporarily override touchstart while gesture is active.
 
2059     function started() {
 
2061       // Listen for touchmove and touchend on the target of touchstart.
 
2062       var target = d3.event.target;
 
2063       d3.select(target).on(touchmove, moved).on(touchend, ended);
 
2064       targets.push(target);
 
2066       // Only track touches started on the same subject element.
 
2067       var changed = d3.event.changedTouches;
 
2068       for (var i = 0, n = changed.length; i < n; ++i) {
 
2069         locations0[changed[i].identifier] = null;
 
2072       var touches = relocate(),
 
2075       if (touches.length === 1) {
 
2076         if (now - touchtime < 500) { // dbltap
 
2078           zoomTo(that, p, locations0[p.identifier], Math.floor(Math.log(view.k) / Math.LN2) + 1);
 
2079           d3_eventPreventDefault();
 
2082       } else if (touches.length > 1) {
 
2083         var p = touches[0], q = touches[1],
 
2084             dx = p[0] - q[0], dy = p[1] - q[1];
 
2085         distance0 = dx * dx + dy * dy;
 
2090       var touches = d3.touches(that),
 
2094       d3_selection_interrupt.call(that);
 
2096       for (var i = 0, n = touches.length; i < n; ++i, l1 = null) {
 
2098         if (l1 = locations0[p1.identifier]) {
 
2105         var distance1 = (distance1 = p1[0] - p0[0]) * distance1 + (distance1 = p1[1] - p0[1]) * distance1,
 
2106             scale1 = distance0 && Math.sqrt(distance1 / distance0);
 
2107         p0 = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2];
 
2108         l0 = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];
 
2109         scaleTo(scale1 * scale0);
 
2113       translateTo(p0, l0);
 
2118       // If there are any globally-active touches remaining, remove the ended
 
2119       // touches from locations0.
 
2120       if (d3.event.touches.length) {
 
2121         var changed = d3.event.changedTouches;
 
2122         for (var i = 0, n = changed.length; i < n; ++i) {
 
2123           delete locations0[changed[i].identifier];
 
2125         // If locations0 is not empty, then relocate and continue listening for
 
2126         // touchmove and touchend.
 
2127         for (var identifier in locations0) {
 
2128           return void relocate(); // locations may have detached due to rotation
 
2131       // Otherwise, remove touchmove and touchend listeners.
 
2132       d3.selectAll(targets).on(zoomName, null);
 
2133       subject.on(mousedown, mousedowned).on(touchstart, touchstarted);
 
2135       zoomended(dispatch);
 
2139   function mousewheeled() {
 
2140     var dispatch = event.of(this, arguments);
 
2141     if (mousewheelTimer) clearTimeout(mousewheelTimer);
 
2142     else d3_selection_interrupt.call(this), translate0 = location(center0 = center || d3.mouse(this)), zoomstarted(dispatch);
 
2143     mousewheelTimer = setTimeout(function() { mousewheelTimer = null; zoomended(dispatch); }, 50);
 
2144     d3_eventPreventDefault();
 
2145     scaleTo(Math.pow(2, d3_behavior_zoomDelta() * .002) * view.k);
 
2146     translateTo(center0, translate0);
 
2150   function dblclicked() {
 
2151     var p = d3.mouse(this),
 
2152         k = Math.log(view.k) / Math.LN2;
 
2154     zoomTo(this, p, location(p), d3.event.shiftKey ? Math.ceil(k) - 1 : Math.floor(k) + 1);
 
2157   return d3.rebind(zoom, event, "on");
 
2160 var d3_behavior_zoomInfinity = [0, Infinity], // default scale extent
 
2161     d3_behavior_zoomDelta, // initialized lazily
 
2162     d3_behavior_zoomWheel;
 
2163 function d3_functor(v) {
 
2164   return typeof v === "function" ? v : function() { return v; };
 
2167 d3.functor = d3_functor;
 
2169 d3.touch = function(container, touches, identifier) {
 
2170   if (arguments.length < 3) identifier = touches, touches = d3_eventSource().changedTouches;
 
2171   if (touches) for (var i = 0, n = touches.length, touch; i < n; ++i) {
 
2172     if ((touch = touches[i]).identifier === identifier) {
 
2173       return d3_mousePoint(container, touch);
 
2178 var d3_timer_queueHead,
 
2180     d3_timer_interval, // is an interval (or frame) active?
 
2181     d3_timer_timeout, // is a timeout active?
 
2182     d3_timer_active, // active timer object
 
2183     d3_timer_frame = this[d3_vendorSymbol(this, "requestAnimationFrame")] || function(callback) { setTimeout(callback, 17); };
 
2185 // The timer will continue to fire until callback returns true.
 
2186 d3.timer = function(callback, delay, then) {
 
2187   var n = arguments.length;
 
2188   if (n < 2) delay = 0;
 
2189   if (n < 3) then = Date.now();
 
2191   // Add the callback to the tail of the queue.
 
2192   var time = then + delay, timer = {c: callback, t: time, f: false, n: null};
 
2193   if (d3_timer_queueTail) d3_timer_queueTail.n = timer;
 
2194   else d3_timer_queueHead = timer;
 
2195   d3_timer_queueTail = timer;
 
2198   if (!d3_timer_interval) {
 
2199     d3_timer_timeout = clearTimeout(d3_timer_timeout);
 
2200     d3_timer_interval = 1;
 
2201     d3_timer_frame(d3_timer_step);
 
2205 function d3_timer_step() {
 
2206   var now = d3_timer_mark(),
 
2207       delay = d3_timer_sweep() - now;
 
2209     if (isFinite(delay)) {
 
2210       clearTimeout(d3_timer_timeout);
 
2211       d3_timer_timeout = setTimeout(d3_timer_step, delay);
 
2213     d3_timer_interval = 0;
 
2215     d3_timer_interval = 1;
 
2216     d3_timer_frame(d3_timer_step);
 
2220 d3.timer.flush = function() {
 
2225 function d3_timer_mark() {
 
2226   var now = Date.now();
 
2227   d3_timer_active = d3_timer_queueHead;
 
2228   while (d3_timer_active) {
 
2229     if (now >= d3_timer_active.t) d3_timer_active.f = d3_timer_active.c(now - d3_timer_active.t);
 
2230     d3_timer_active = d3_timer_active.n;
 
2235 // Flush after callbacks to avoid concurrent queue modification.
 
2236 // Returns the time of the earliest active timer, post-sweep.
 
2237 function d3_timer_sweep() {
 
2239       t1 = d3_timer_queueHead,
 
2243       t1 = t0 ? t0.n = t1.n : d3_timer_queueHead = t1.n;
 
2245       if (t1.t < time) time = t1.t;
 
2249   d3_timer_queueTail = t0;
 
2254 d3.geo.stream = function(object, listener) {
 
2255   if (object && d3_geo_streamObjectType.hasOwnProperty(object.type)) {
 
2256     d3_geo_streamObjectType[object.type](object, listener);
 
2258     d3_geo_streamGeometry(object, listener);
 
2262 function d3_geo_streamGeometry(geometry, listener) {
 
2263   if (geometry && d3_geo_streamGeometryType.hasOwnProperty(geometry.type)) {
 
2264     d3_geo_streamGeometryType[geometry.type](geometry, listener);
 
2268 var d3_geo_streamObjectType = {
 
2269   Feature: function(feature, listener) {
 
2270     d3_geo_streamGeometry(feature.geometry, listener);
 
2272   FeatureCollection: function(object, listener) {
 
2273     var features = object.features, i = -1, n = features.length;
 
2274     while (++i < n) d3_geo_streamGeometry(features[i].geometry, listener);
 
2278 var d3_geo_streamGeometryType = {
 
2279   Sphere: function(object, listener) {
 
2282   Point: function(object, listener) {
 
2283     object = object.coordinates;
 
2284     listener.point(object[0], object[1], object[2]);
 
2286   MultiPoint: function(object, listener) {
 
2287     var coordinates = object.coordinates, i = -1, n = coordinates.length;
 
2288     while (++i < n) object = coordinates[i], listener.point(object[0], object[1], object[2]);
 
2290   LineString: function(object, listener) {
 
2291     d3_geo_streamLine(object.coordinates, listener, 0);
 
2293   MultiLineString: function(object, listener) {
 
2294     var coordinates = object.coordinates, i = -1, n = coordinates.length;
 
2295     while (++i < n) d3_geo_streamLine(coordinates[i], listener, 0);
 
2297   Polygon: function(object, listener) {
 
2298     d3_geo_streamPolygon(object.coordinates, listener);
 
2300   MultiPolygon: function(object, listener) {
 
2301     var coordinates = object.coordinates, i = -1, n = coordinates.length;
 
2302     while (++i < n) d3_geo_streamPolygon(coordinates[i], listener);
 
2304   GeometryCollection: function(object, listener) {
 
2305     var geometries = object.geometries, i = -1, n = geometries.length;
 
2306     while (++i < n) d3_geo_streamGeometry(geometries[i], listener);
 
2310 function d3_geo_streamLine(coordinates, listener, closed) {
 
2311   var i = -1, n = coordinates.length - closed, coordinate;
 
2312   listener.lineStart();
 
2313   while (++i < n) coordinate = coordinates[i], listener.point(coordinate[0], coordinate[1], coordinate[2]);
 
2317 function d3_geo_streamPolygon(coordinates, listener) {
 
2318   var i = -1, n = coordinates.length;
 
2319   listener.polygonStart();
 
2320   while (++i < n) d3_geo_streamLine(coordinates[i], listener, 1);
 
2321   listener.polygonEnd();
 
2324 d3.geo.length = function(object) {
 
2325   d3_geo_lengthSum = 0;
 
2326   d3.geo.stream(object, d3_geo_length);
 
2327   return d3_geo_lengthSum;
 
2330 var d3_geo_lengthSum;
 
2332 var d3_geo_length = {
 
2335   lineStart: d3_geo_lengthLineStart,
 
2337   polygonStart: d3_noop,
 
2341 function d3_geo_lengthLineStart() {
 
2342   var λ0, sinφ0, cosφ0;
 
2344   d3_geo_length.point = function(λ, φ) {
 
2345     λ0 = λ * d3_radians, sinφ0 = Math.sin(φ *= d3_radians), cosφ0 = Math.cos(φ);
 
2346     d3_geo_length.point = nextPoint;
 
2349   d3_geo_length.lineEnd = function() {
 
2350     d3_geo_length.point = d3_geo_length.lineEnd = d3_noop;
 
2353   function nextPoint(λ, φ) {
 
2354     var sinφ = Math.sin(φ *= d3_radians),
 
2356         t = abs((λ *= d3_radians) - λ0),
 
2357         cosΔλ = Math.cos(t);
 
2358     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Δλ);
 
2359     λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ;
 
2362 function d3_identity(d) {
 
2365 function d3_true() {
 
2369 function d3_geo_spherical(cartesian) {
 
2371     Math.atan2(cartesian[1], cartesian[0]),
 
2372     d3_asin(cartesian[2])
 
2376 function d3_geo_sphericalEqual(a, b) {
 
2377   return abs(a[0] - b[0]) < ε && abs(a[1] - b[1]) < ε;
 
2380 // General spherical polygon clipping algorithm: takes a polygon, cuts it into
 
2381 // visible line segments and rejoins the segments by interpolating along the
 
2383 function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) {
 
2387   segments.forEach(function(segment) {
 
2388     if ((n = segment.length - 1) <= 0) return;
 
2389     var n, p0 = segment[0], p1 = segment[n];
 
2391     // If the first and last points of a segment are coincident, then treat as
 
2393     // TODO if all rings are closed, then the winding order of the exterior
 
2394     // ring should be checked.
 
2395     if (d3_geo_sphericalEqual(p0, p1)) {
 
2396       listener.lineStart();
 
2397       for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]);
 
2402     var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true),
 
2403         b = new d3_geo_clipPolygonIntersection(p0, null, a, false);
 
2407     a = new d3_geo_clipPolygonIntersection(p1, segment, null, false);
 
2408     b = new d3_geo_clipPolygonIntersection(p1, null, a, true);
 
2414   d3_geo_clipPolygonLinkCircular(subject);
 
2415   d3_geo_clipPolygonLinkCircular(clip);
 
2416   if (!subject.length) return;
 
2418   for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) {
 
2419     clip[i].e = entry = !entry;
 
2422   var start = subject[0],
 
2426     // Find first unvisited intersection.
 
2427     var current = start,
 
2429     while (current.v) if ((current = current.n) === start) return;
 
2431     listener.lineStart();
 
2433       current.v = current.o.v = true;
 
2436           for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]);
 
2438           interpolate(current.x, current.n.x, 1, listener);
 
2440         current = current.n;
 
2443           points = current.p.z;
 
2444           for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]);
 
2446           interpolate(current.x, current.p.x, -1, listener);
 
2448         current = current.p;
 
2450       current = current.o;
 
2452       isSubject = !isSubject;
 
2453     } while (!current.v);
 
2458 function d3_geo_clipPolygonLinkCircular(array) {
 
2459   if (!(n = array.length)) return;
 
2473 function d3_geo_clipPolygonIntersection(point, points, other, entry) {
 
2476   this.o = other; // another intersection
 
2477   this.e = entry; // is an entry?
 
2478   this.v = false; // visited
 
2479   this.n = this.p = null; // next & previous
 
2482 function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) {
 
2483   return function(rotate, listener) {
 
2484     var line = clipLine(listener),
 
2485         rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]);
 
2489       lineStart: lineStart,
 
2491       polygonStart: function() {
 
2492         clip.point = pointRing;
 
2493         clip.lineStart = ringStart;
 
2494         clip.lineEnd = ringEnd;
 
2498       polygonEnd: function() {
 
2500         clip.lineStart = lineStart;
 
2501         clip.lineEnd = lineEnd;
 
2503         segments = d3.merge(segments);
 
2504         var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon);
 
2505         if (segments.length) {
 
2506           if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
 
2507           d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener);
 
2508         } else if (clipStartInside) {
 
2509           if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
 
2510           listener.lineStart();
 
2511           interpolate(null, null, 1, listener);
 
2514         if (polygonStarted) listener.polygonEnd(), polygonStarted = false;
 
2515         segments = polygon = null;
 
2517       sphere: function() {
 
2518         listener.polygonStart();
 
2519         listener.lineStart();
 
2520         interpolate(null, null, 1, listener);
 
2522         listener.polygonEnd();
 
2526     function point(λ, φ) {
 
2527       var point = rotate(λ, φ);
 
2528       if (pointVisible(λ = point[0], φ = point[1])) listener.point(λ, φ);
 
2530     function pointLine(λ, φ) {
 
2531       var point = rotate(λ, φ);
 
2532       line.point(point[0], point[1]);
 
2534     function lineStart() { clip.point = pointLine; line.lineStart(); }
 
2535     function lineEnd() { clip.point = point; line.lineEnd(); }
 
2539     var buffer = d3_geo_clipBufferListener(),
 
2540         ringListener = clipLine(buffer),
 
2541         polygonStarted = false,
 
2545     function pointRing(λ, φ) {
 
2547       var point = rotate(λ, φ);
 
2548       ringListener.point(point[0], point[1]);
 
2551     function ringStart() {
 
2552       ringListener.lineStart();
 
2556     function ringEnd() {
 
2557       pointRing(ring[0][0], ring[0][1]);
 
2558       ringListener.lineEnd();
 
2560       var clean = ringListener.clean(),
 
2561           ringSegments = buffer.buffer(),
 
2563           n = ringSegments.length;
 
2571       // No intersections.
 
2573         segment = ringSegments[0];
 
2574         var n = segment.length - 1,
 
2578           if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
 
2579           listener.lineStart();
 
2580           while (++i < n) listener.point((point = segment[i])[0], point[1]);
 
2586       // Rejoin connected segments.
 
2587       // TODO reuse bufferListener.rejoin()?
 
2588       if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
 
2590       segments.push(ringSegments.filter(d3_geo_clipSegmentLength1));
 
2597 function d3_geo_clipSegmentLength1(segment) {
 
2598   return segment.length > 1;
 
2601 function d3_geo_clipBufferListener() {
 
2605     lineStart: function() { lines.push(line = []); },
 
2606     point: function(λ, φ) { line.push([λ, φ]); },
 
2608     buffer: function() {
 
2614     rejoin: function() {
 
2615       if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
 
2620 // Intersection points are sorted along the clip edge. For both antimeridian
 
2621 // cutting and circle clipping, the same comparison is used.
 
2622 function d3_geo_clipSort(a, b) {
 
2623   return ((a = a.x)[0] < 0 ? a[1] - halfπ - ε : halfπ - a[1])
 
2624        - ((b = b.x)[0] < 0 ? b[1] - halfπ - ε : halfπ - b[1]);
 
2627 var d3_geo_clipAntimeridian = d3_geo_clip(
 
2629     d3_geo_clipAntimeridianLine,
 
2630     d3_geo_clipAntimeridianInterpolate,
 
2633 // Takes a line and cuts into visible segments. Return values:
 
2634 //   0: there were intersections or the line was empty.
 
2635 //   1: no intersections.
 
2636 //   2: there were intersections, and the first and last segments should be
 
2638 function d3_geo_clipAntimeridianLine(listener) {
 
2642       clean; // no intersections
 
2645     lineStart: function() {
 
2646       listener.lineStart();
 
2649     point: function(λ1, φ1) {
 
2650       var sλ1 = λ1 > 0 ? π : -π,
 
2652       if (abs(dλ - π) < ε) { // line crosses a pole
 
2653         listener.point(λ0, φ0 = (φ0 + φ1) / 2 > 0 ? halfπ : -halfπ);
 
2654         listener.point(sλ0, φ0);
 
2656         listener.lineStart();
 
2657         listener.point(sλ1, φ0);
 
2658         listener.point(λ1, φ0);
 
2660       } else if (sλ0 !== sλ1 && dλ >= π) { // line crosses antimeridian
 
2661         // handle degeneracies
 
2662         if (abs(λ0 - sλ0) < ε) λ0 -= sλ0 * ε;
 
2663         if (abs(λ1 - sλ1) < ε) λ1 -= sλ1 * ε;
 
2664         φ0 = d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1);
 
2665         listener.point(sλ0, φ0);
 
2667         listener.lineStart();
 
2668         listener.point(sλ1, φ0);
 
2671       listener.point(λ0 = λ1, φ0 = φ1);
 
2674     lineEnd: function() {
 
2678     // if there are intersections, we always rejoin the first and last segments.
 
2679     clean: function() { return 2 - clean; }
 
2683 function d3_geo_clipAntimeridianIntersect(λ0, φ0, λ1, φ1) {
 
2686       sinλ0_λ1 = Math.sin(λ0 - λ1);
 
2687   return abs(sinλ0_λ1) > ε
 
2688       ? Math.atan((Math.sin(φ0) * (cosφ1 = Math.cos(φ1)) * Math.sin(λ1)
 
2689                  - Math.sin(φ1) * (cosφ0 = Math.cos(φ0)) * Math.sin(λ0))
 
2690                  / (cosφ0 * cosφ1 * sinλ0_λ1))
 
2694 function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) {
 
2697     φ = direction * halfπ;
 
2698     listener.point(-π,  φ);
 
2699     listener.point( 0,  φ);
 
2700     listener.point( π,  φ);
 
2701     listener.point( π,  0);
 
2702     listener.point( π, -φ);
 
2703     listener.point( 0, -φ);
 
2704     listener.point(-π, -φ);
 
2705     listener.point(-π,  0);
 
2706     listener.point(-π,  φ);
 
2707   } else if (abs(from[0] - to[0]) > ε) {
 
2708     var s = from[0] < to[0] ? π : -π;
 
2709     φ = direction * s / 2;
 
2710     listener.point(-s, φ);
 
2711     listener.point( 0, φ);
 
2712     listener.point( s, φ);
 
2714     listener.point(to[0], to[1]);
 
2718 // cross and scale return new vectors,
 
2719 // whereas add and normalize operate in-place
 
2721 function d3_geo_cartesian(spherical) {
 
2722   var λ = spherical[0],
 
2732 function d3_geo_cartesianDot(a, b) {
 
2733   return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
 
2736 function d3_geo_cartesianCross(a, b) {
 
2738     a[1] * b[2] - a[2] * b[1],
 
2739     a[2] * b[0] - a[0] * b[2],
 
2740     a[0] * b[1] - a[1] * b[0]
 
2744 function d3_geo_cartesianAdd(a, b) {
 
2750 function d3_geo_cartesianScale(vector, k) {
 
2758 function d3_geo_cartesianNormalize(d) {
 
2759   var l = Math.sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
 
2764 function d3_geo_compose(a, b) {
 
2766   function compose(x, y) {
 
2767     return x = a(x, y), b(x[0], x[1]);
 
2770   if (a.invert && b.invert) compose.invert = function(x, y) {
 
2771     return x = b.invert(x, y), x && a.invert(x[0], x[1]);
 
2777 function d3_geo_equirectangular(λ, φ) {
 
2781 (d3.geo.equirectangular = function() {
 
2782   return d3_geo_projection(d3_geo_equirectangular);
 
2783 }).raw = d3_geo_equirectangular.invert = d3_geo_equirectangular;
 
2785 d3.geo.rotation = function(rotate) {
 
2786   rotate = d3_geo_rotation(rotate[0] % 360 * d3_radians, rotate[1] * d3_radians, rotate.length > 2 ? rotate[2] * d3_radians : 0);
 
2788   function forward(coordinates) {
 
2789     coordinates = rotate(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
 
2790     return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
 
2793   forward.invert = function(coordinates) {
 
2794     coordinates = rotate.invert(coordinates[0] * d3_radians, coordinates[1] * d3_radians);
 
2795     return coordinates[0] *= d3_degrees, coordinates[1] *= d3_degrees, coordinates;
 
2801 function d3_geo_identityRotation(λ, φ) {
 
2802   return [λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ];
 
2805 d3_geo_identityRotation.invert = d3_geo_equirectangular;
 
2807 // Note: |δλ| must be < 2π
 
2808 function d3_geo_rotation(δλ, δφ, δγ) {
 
2809   return δλ ? (δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ))
 
2810     : d3_geo_rotationλ(δλ))
 
2811     : (δφ || δγ ? d3_geo_rotationφγ(δφ, δγ)
 
2812     : d3_geo_identityRotation);
 
2815 function d3_geo_forwardRotationλ(δλ) {
 
2816   return function(λ, φ) {
 
2817     return λ += δλ, [λ > π ? λ - τ : λ < -π ? λ + τ : λ, φ];
 
2821 function d3_geo_rotationλ(δλ) {
 
2822   var rotation = d3_geo_forwardRotationλ(δλ);
 
2823   rotation.invert = d3_geo_forwardRotationλ(-δλ);
 
2827 function d3_geo_rotationφγ(δφ, δγ) {
 
2828   var cosδφ = Math.cos(δφ),
 
2829       sinδφ = Math.sin(δφ),
 
2830       cosδγ = Math.cos(δγ),
 
2831       sinδγ = Math.sin(δγ);
 
2833   function rotation(λ, φ) {
 
2834     var cosφ = Math.cos(φ),
 
2835         x = Math.cos(λ) * cosφ,
 
2836         y = Math.sin(λ) * cosφ,
 
2838         k = z * cosδφ + x * sinδφ;
 
2840       Math.atan2(y * cosδγ - k * sinδγ, x * cosδφ - z * sinδφ),
 
2841       d3_asin(k * cosδγ + y * sinδγ)
 
2845   rotation.invert = function(λ, φ) {
 
2846     var cosφ = Math.cos(φ),
 
2847         x = Math.cos(λ) * cosφ,
 
2848         y = Math.sin(λ) * cosφ,
 
2850         k = z * cosδγ - y * sinδγ;
 
2852       Math.atan2(y * cosδγ + z * sinδγ, x * cosδφ + k * sinδφ),
 
2853       d3_asin(k * cosδφ - x * sinδφ)
 
2860 d3.geo.circle = function() {
 
2861   var origin = [0, 0],
 
2867     var center = typeof origin === "function" ? origin.apply(this, arguments) : origin,
 
2868         rotate = d3_geo_rotation(-center[0] * d3_radians, -center[1] * d3_radians, 0).invert,
 
2871     interpolate(null, null, 1, {
 
2872       point: function(x, y) {
 
2873         ring.push(x = rotate(x, y));
 
2874         x[0] *= d3_degrees, x[1] *= d3_degrees;
 
2878     return {type: "Polygon", coordinates: [ring]};
 
2881   circle.origin = function(x) {
 
2882     if (!arguments.length) return origin;
 
2887   circle.angle = function(x) {
 
2888     if (!arguments.length) return angle;
 
2889     interpolate = d3_geo_circleInterpolate((angle = +x) * d3_radians, precision * d3_radians);
 
2893   circle.precision = function(_) {
 
2894     if (!arguments.length) return precision;
 
2895     interpolate = d3_geo_circleInterpolate(angle * d3_radians, (precision = +_) * d3_radians);
 
2899   return circle.angle(90);
 
2902 // Interpolates along a circle centered at [0°, 0°], with a given radius and
 
2904 function d3_geo_circleInterpolate(radius, precision) {
 
2905   var cr = Math.cos(radius),
 
2906       sr = Math.sin(radius);
 
2907   return function(from, to, direction, listener) {
 
2908     var step = direction * precision;
 
2910       from = d3_geo_circleAngle(cr, from);
 
2911       to = d3_geo_circleAngle(cr, to);
 
2912       if (direction > 0 ? from < to: from > to) from += direction * τ;
 
2914       from = radius + direction * τ;
 
2915       to = radius - .5 * step;
 
2917     for (var point, t = from; direction > 0 ? t > to : t < to; t -= step) {
 
2918       listener.point((point = d3_geo_spherical([
 
2927 // Signed angle of a cartesian point relative to [cr, 0, 0].
 
2928 function d3_geo_circleAngle(cr, point) {
 
2929   var a = d3_geo_cartesian(point);
 
2931   d3_geo_cartesianNormalize(a);
 
2932   var angle = d3_acos(-a[1]);
 
2933   return ((-a[2] < 0 ? -angle : angle) + 2 * Math.PI - ε) % (2 * Math.PI);
 
2935 // Adds floating point numbers with twice the normal precision.
 
2936 // Reference: J. R. Shewchuk, Adaptive Precision Floating-Point Arithmetic and
 
2937 // Fast Robust Geometric Predicates, Discrete & Computational Geometry 18(3)
 
2939 // Code adapted from GeographicLib by Charles F. F. Karney,
 
2940 // http://geographiclib.sourceforge.net/
 
2941 // See lib/geographiclib/LICENSE for details.
 
2943 function d3_adder() {}
 
2945 d3_adder.prototype = {
 
2946   s: 0, // rounded value
 
2947   t: 0, // exact error
 
2949     d3_adderSum(y, this.t, d3_adderTemp);
 
2950     d3_adderSum(d3_adderTemp.s, this.s, this);
 
2951     if (this.s) this.t += d3_adderTemp.t;
 
2952     else this.s = d3_adderTemp.t;
 
2955     this.s = this.t = 0;
 
2957   valueOf: function() {
 
2962 var d3_adderTemp = new d3_adder;
 
2964 function d3_adderSum(a, b, o) {
 
2965   var x = o.s = a + b, // a + b
 
2966       bv = x - a, av = x - bv; // b_virtual & a_virtual
 
2967   o.t = (a - av) + (b - bv); // a_roundoff + b_roundoff
 
2970 d3.geo.area = function(object) {
 
2972   d3.geo.stream(object, d3_geo_area);
 
2973   return d3_geo_areaSum;
 
2977     d3_geo_areaRingSum = new d3_adder;
 
2980   sphere: function() { d3_geo_areaSum += 4 * π; },
 
2985   // Only count area for polygon rings.
 
2986   polygonStart: function() {
 
2987     d3_geo_areaRingSum.reset();
 
2988     d3_geo_area.lineStart = d3_geo_areaRingStart;
 
2990   polygonEnd: function() {
 
2991     var area = 2 * d3_geo_areaRingSum;
 
2992     d3_geo_areaSum += area < 0 ? 4 * π + area : area;
 
2993     d3_geo_area.lineStart = d3_geo_area.lineEnd = d3_geo_area.point = d3_noop;
 
2997 function d3_geo_areaRingStart() {
 
2998   var λ00, φ00, λ0, cosφ0, sinφ0; // start point and previous point
 
3000   // For the first point, …
 
3001   d3_geo_area.point = function(λ, φ) {
 
3002     d3_geo_area.point = nextPoint;
 
3003     λ0 = (λ00 = λ) * d3_radians, cosφ0 = Math.cos(φ = (φ00 = φ) * d3_radians / 2 + π / 4), sinφ0 = Math.sin(φ);
 
3006   // For subsequent points, …
 
3007   function nextPoint(λ, φ) {
 
3009     φ = φ * d3_radians / 2 + π / 4; // half the angular distance from south pole
 
3011     // Spherical excess E for a spherical triangle with vertices: south pole,
 
3012     // previous point, current point.  Uses a formula derived from Cagnoli’s
 
3013     // theorem.  See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2).
 
3015         sdλ = dλ >= 0 ? 1 : -1,
 
3020         u = cosφ0 * cosφ + k * Math.cos(adλ),
 
3021         v = k * sdλ * Math.sin(adλ);
 
3022     d3_geo_areaRingSum.add(Math.atan2(v, u));
 
3024     // Advance the previous points.
 
3025     λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ;
 
3028   // For the last point, return to the start.
 
3029   d3_geo_area.lineEnd = function() {
 
3030     nextPoint(λ00, φ00);
 
3034 function d3_geo_pointInPolygon(point, polygon) {
 
3035   var meridian = point[0],
 
3036       parallel = point[1],
 
3037       meridianNormal = [Math.sin(meridian), -Math.cos(meridian), 0],
 
3040   d3_geo_areaRingSum.reset();
 
3042   for (var i = 0, n = polygon.length; i < n; ++i) {
 
3043     var ring = polygon[i],
 
3046     var point0 = ring[0],
 
3048         φ0 = point0[1] / 2 + π / 4,
 
3049         sinφ0 = Math.sin(φ0),
 
3050         cosφ0 = Math.cos(φ0),
 
3057           φ = point[1] / 2 + π / 4,
 
3061           sdλ = dλ >= 0 ? 1 : -1,
 
3063           antimeridian = adλ > π,
 
3065       d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ)));
 
3067       polarAngle += antimeridian ? dλ + sdλ * τ : dλ;
 
3069       // Are the longitudes either side of the point's meridian, and are the
 
3070       // latitudes smaller than the parallel?
 
3071       if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) {
 
3072         var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point));
 
3073         d3_geo_cartesianNormalize(arc);
 
3074         var intersection = d3_geo_cartesianCross(meridianNormal, arc);
 
3075         d3_geo_cartesianNormalize(intersection);
 
3076         var φarc = (antimeridian ^ dλ >= 0 ? -1 : 1) * d3_asin(intersection[2]);
 
3077         if (parallel > φarc || parallel === φarc && (arc[0] || arc[1])) {
 
3078           winding += antimeridian ^ dλ >= 0 ? 1 : -1;
 
3082       λ0 = λ, sinφ0 = sinφ, cosφ0 = cosφ, point0 = point;
 
3086   // First, determine whether the South pole is inside or outside:
 
3089   // * the polygon winds around it in a clockwise direction.
 
3090   // * the polygon does not (cumulatively) wind around it, but has a negative
 
3091   //   (counter-clockwise) area.
 
3093   // Second, count the (signed) number of times a segment crosses a meridian
 
3094   // from the point to the South pole.  If it is zero, then the point is the
 
3095   // same side as the South pole.
 
3097   return (polarAngle < -ε || polarAngle < ε && d3_geo_areaRingSum < 0) ^ (winding & 1);
 
3100 // Clip features against a small circle centered at [0°, 0°].
 
3101 function d3_geo_clipCircle(radius) {
 
3102   var cr = Math.cos(radius),
 
3103       smallRadius = cr > 0,
 
3104       notHemisphere = abs(cr) > ε, // TODO optimise for this common case
 
3105       interpolate = d3_geo_circleInterpolate(radius, 6 * d3_radians);
 
3107   return d3_geo_clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-π, radius - π]);
 
3109   function visible(λ, φ) {
 
3110     return Math.cos(λ) * Math.cos(φ) > cr;
 
3113   // Takes a line and cuts into visible segments. Return values used for
 
3114   // polygon clipping:
 
3115   //   0: there were intersections or the line was empty.
 
3116   //   1: no intersections.
 
3117   //   2: there were intersections, and the first and last segments should be
 
3119   function clipLine(listener) {
 
3120     var point0, // previous point
 
3121         c0, // code for previous point
 
3122         v0, // visibility of previous point
 
3123         v00, // visibility of first point
 
3124         clean; // no intersections
 
3126       lineStart: function() {
 
3130       point: function(λ, φ) {
 
3131         var point1 = [λ, φ],
 
3135               ? v ? 0 : code(λ, φ)
 
3136               : v ? code(λ + (λ < 0 ? π : -π), φ) : 0;
 
3137         if (!point0 && (v00 = v0 = v)) listener.lineStart();
 
3138         // Handle degeneracies.
 
3139         // TODO ignore if not clipping polygons.
 
3141           point2 = intersect(point0, point1);
 
3142           if (d3_geo_sphericalEqual(point0, point2) || d3_geo_sphericalEqual(point1, point2)) {
 
3145             v = visible(point1[0], point1[1]);
 
3152             listener.lineStart();
 
3153             point2 = intersect(point1, point0);
 
3154             listener.point(point2[0], point2[1]);
 
3157             point2 = intersect(point0, point1);
 
3158             listener.point(point2[0], point2[1]);
 
3162         } else if (notHemisphere && point0 && smallRadius ^ v) {
 
3164           // If the codes for two points are different, or are both zero,
 
3165           // and there this segment intersects with the small circle.
 
3166           if (!(c & c0) && (t = intersect(point1, point0, true))) {
 
3169               listener.lineStart();
 
3170               listener.point(t[0][0], t[0][1]);
 
3171               listener.point(t[1][0], t[1][1]);
 
3174               listener.point(t[1][0], t[1][1]);
 
3176               listener.lineStart();
 
3177               listener.point(t[0][0], t[0][1]);
 
3181         if (v && (!point0 || !d3_geo_sphericalEqual(point0, point1))) {
 
3182           listener.point(point1[0], point1[1]);
 
3184         point0 = point1, v0 = v, c0 = c;
 
3186       lineEnd: function() {
 
3187         if (v0) listener.lineEnd();
 
3190       // Rejoin first and last segments if there were intersections and the first
 
3191       // and last points were visible.
 
3192       clean: function() { return clean | ((v00 && v0) << 1); }
 
3196   // Intersects the great circle between a and b with the clip circle.
 
3197   function intersect(a, b, two) {
 
3198     var pa = d3_geo_cartesian(a),
 
3199         pb = d3_geo_cartesian(b);
 
3201     // We have two planes, n1.p = d1 and n2.p = d2.
 
3202     // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2).
 
3203     var n1 = [1, 0, 0], // normal
 
3204         n2 = d3_geo_cartesianCross(pa, pb),
 
3205         n2n2 = d3_geo_cartesianDot(n2, n2),
 
3206         n1n2 = n2[0], // d3_geo_cartesianDot(n1, n2),
 
3207         determinant = n2n2 - n1n2 * n1n2;
 
3209     // Two polar points.
 
3210     if (!determinant) return !two && a;
 
3212     var c1 =  cr * n2n2 / determinant,
 
3213         c2 = -cr * n1n2 / determinant,
 
3214         n1xn2 = d3_geo_cartesianCross(n1, n2),
 
3215         A = d3_geo_cartesianScale(n1, c1),
 
3216         B = d3_geo_cartesianScale(n2, c2);
 
3217     d3_geo_cartesianAdd(A, B);
 
3219     // Solve |p(t)|^2 = 1.
 
3221         w = d3_geo_cartesianDot(A, u),
 
3222         uu = d3_geo_cartesianDot(u, u),
 
3223         t2 = w * w - uu * (d3_geo_cartesianDot(A, A) - 1);
 
3227     var t = Math.sqrt(t2),
 
3228         q = d3_geo_cartesianScale(u, (-w - t) / uu);
 
3229     d3_geo_cartesianAdd(q, A);
 
3230     q = d3_geo_spherical(q);
 
3233     // Two intersection points.
 
3239     if (λ1 < λ0) z = λ0, λ0 = λ1, λ1 = z;
 
3241         polar = abs(δλ - π) < ε,
 
3242         meridian = polar || δλ < ε;
 
3244     if (!polar && φ1 < φ0) z = φ0, φ0 = φ1, φ1 = z;
 
3246     // Check that the first point is between a and b.
 
3249           ? φ0 + φ1 > 0 ^ q[1] < (abs(q[0] - λ0) < ε ? φ0 : φ1)
 
3250           : φ0 <= q[1] && q[1] <= φ1
 
3251         : δλ > π ^ (λ0 <= q[0] && q[0] <= λ1)) {
 
3252       var q1 = d3_geo_cartesianScale(u, (-w + t) / uu);
 
3253       d3_geo_cartesianAdd(q1, A);
 
3254       return [q, d3_geo_spherical(q1)];
 
3258   // Generates a 4-bit vector representing the location of a point relative to
 
3259   // the small circle's bounding box.
 
3260   function code(λ, φ) {
 
3261     var r = smallRadius ? radius : π - radius,
 
3263     if (λ < -r) code |= 1; // left
 
3264     else if (λ > r) code |= 2; // right
 
3265     if (φ < -r) code |= 4; // below
 
3266     else if (φ > r) code |= 8; // above
 
3271 // Liang–Barsky line clipping.
 
3272 function d3_geom_clipLine(x0, y0, x1, y1) {
 
3273   return function(line) {
 
3287     if (!dx && r > 0) return;
 
3292     } else if (dx > 0) {
 
3298     if (!dx && r < 0) return;
 
3303     } else if (dx > 0) {
 
3309     if (!dy && r > 0) return;
 
3314     } else if (dy > 0) {
 
3320     if (!dy && r < 0) return;
 
3325     } else if (dy > 0) {
 
3330     if (t0 > 0) line.a = {x: ax + t0 * dx, y: ay + t0 * dy};
 
3331     if (t1 < 1) line.b = {x: ax + t1 * dx, y: ay + t1 * dy};
 
3336 var d3_geo_clipExtentMAX = 1e9;
 
3338 d3.geo.clipExtent = function() {
 
3343         stream: function(output) {
 
3344           if (stream) stream.valid = false;
 
3345           stream = clip(output);
 
3346           stream.valid = true; // allow caching by d3.geo.path
 
3349         extent: function(_) {
 
3350           if (!arguments.length) return [[x0, y0], [x1, y1]];
 
3351           clip = d3_geo_clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]);
 
3352           if (stream) stream.valid = false, stream = null;
 
3356   return clipExtent.extent([[0, 0], [960, 500]]);
 
3359 function d3_geo_clipExtent(x0, y0, x1, y1) {
 
3360   return function(listener) {
 
3361     var listener_ = listener,
 
3362         bufferListener = d3_geo_clipBufferListener(),
 
3363         clipLine = d3_geom_clipLine(x0, y0, x1, y1),
 
3370       lineStart: lineStart,
 
3372       polygonStart: function() {
 
3373         listener = bufferListener;
 
3378       polygonEnd: function() {
 
3379         listener = listener_;
 
3380         segments = d3.merge(segments);
 
3381         var clipStartInside = insidePolygon([x0, y1]),
 
3382             inside = clean && clipStartInside,
 
3383             visible = segments.length;
 
3384         if (inside || visible) {
 
3385           listener.polygonStart();
 
3387             listener.lineStart();
 
3388             interpolate(null, null, 1, listener);
 
3392             d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener);
 
3394           listener.polygonEnd();
 
3396         segments = polygon = ring = null;
 
3400     function insidePolygon(p) {
 
3401       var wn = 0, // the winding number counter
 
3405       for (var i = 0; i < n; ++i) {
 
3406         for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) {
 
3409             if (b[1] >  y && d3_cross2d(a, b, p) > 0) ++wn;
 
3411             if (b[1] <= y && d3_cross2d(a, b, p) < 0) --wn;
 
3419     function interpolate(from, to, direction, listener) {
 
3422           (a = corner(from, direction)) !== (a1 = corner(to, direction)) ||
 
3423           comparePoints(from, to) < 0 ^ direction > 0) {
 
3425           listener.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
 
3426         } while ((a = (a + direction + 4) % 4) !== a1);
 
3428         listener.point(to[0], to[1]);
 
3432     function pointVisible(x, y) {
 
3433       return x0 <= x && x <= x1 && y0 <= y && y <= y1;
 
3436     function point(x, y) {
 
3437       if (pointVisible(x, y)) listener.point(x, y);
 
3440     var x__, y__, v__, // first point
 
3441         x_, y_, v_, // previous point
 
3445     function lineStart() {
 
3446       clip.point = linePoint;
 
3447       if (polygon) polygon.push(ring = []);
 
3453     function lineEnd() {
 
3454       // TODO rather than special-case polygons, simply handle them separately.
 
3455       // Ideally, coincident intersection points should be jittered to avoid
 
3458         linePoint(x__, y__);
 
3459         if (v__ && v_) bufferListener.rejoin();
 
3460         segments.push(bufferListener.buffer());
 
3463       if (v_) listener.lineEnd();
 
3466     function linePoint(x, y) {
 
3467       x = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, x));
 
3468       y = Math.max(-d3_geo_clipExtentMAX, Math.min(d3_geo_clipExtentMAX, y));
 
3469       var v = pointVisible(x, y);
 
3470       if (polygon) ring.push([x, y]);
 
3472         x__ = x, y__ = y, v__ = v;
 
3475           listener.lineStart();
 
3476           listener.point(x, y);
 
3479         if (v && v_) listener.point(x, y);
 
3481           var l = {a: {x: x_, y: y_}, b: {x: x, y: y}};
 
3484               listener.lineStart();
 
3485               listener.point(l.a.x, l.a.y);
 
3487             listener.point(l.b.x, l.b.y);
 
3488             if (!v) listener.lineEnd();
 
3491             listener.lineStart();
 
3492             listener.point(x, y);
 
3497       x_ = x, y_ = y, v_ = v;
 
3503   function corner(p, direction) {
 
3504     return abs(p[0] - x0) < ε ? direction > 0 ? 0 : 3
 
3505         : abs(p[0] - x1) < ε ? direction > 0 ? 2 : 1
 
3506         : abs(p[1] - y0) < ε ? direction > 0 ? 1 : 0
 
3507         : direction > 0 ? 3 : 2; // abs(p[1] - y1) < ε
 
3510   function compare(a, b) {
 
3511     return comparePoints(a.x, b.x);
 
3514   function comparePoints(a, b) {
 
3515     var ca = corner(a, 1),
 
3517     return ca !== cb ? ca - cb
 
3518         : ca === 0 ? b[1] - a[1]
 
3519         : ca === 1 ? a[0] - b[0]
 
3520         : ca === 2 ? a[1] - b[1]
 
3525 function d3_geo_conic(projectAt) {
 
3528       m = d3_geo_projectionMutator(projectAt),
 
3531   p.parallels = function(_) {
 
3532     if (!arguments.length) return [φ0 / π * 180, φ1 / π * 180];
 
3533     return m(φ0 = _[0] * π / 180, φ1 = _[1] * π / 180);
 
3539 function d3_geo_conicEqualArea(φ0, φ1) {
 
3540   var sinφ0 = Math.sin(φ0),
 
3541       n = (sinφ0 + Math.sin(φ1)) / 2,
 
3542       C = 1 + sinφ0 * (2 * n - sinφ0),
 
3543       ρ0 = Math.sqrt(C) / n;
 
3545   function forward(λ, φ) {
 
3546     var ρ = Math.sqrt(C - 2 * n * Math.sin(φ)) / n;
 
3548       ρ * Math.sin(λ *= n),
 
3549       ρ0 - ρ * Math.cos(λ)
 
3553   forward.invert = function(x, y) {
 
3556       Math.atan2(x, ρ0_y) / n,
 
3557       d3_asin((C - (x * x + ρ0_y * ρ0_y) * n * n) / (2 * n))
 
3564 (d3.geo.conicEqualArea = function() {
 
3565   return d3_geo_conic(d3_geo_conicEqualArea);
 
3566 }).raw = d3_geo_conicEqualArea;
 
3569 d3.geo.albers = function() {
 
3570   return d3.geo.conicEqualArea()
 
3572       .center([-.6, 38.7])
 
3573       .parallels([29.5, 45.5])
 
3577 // A composite projection for the United States, configured by default for
 
3578 // 960×500. Also works quite well at 960×600 with scale 1285. The set of
 
3579 // standard parallels for each region comes from USGS, which is published here:
 
3580 // http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers
 
3581 d3.geo.albersUsa = function() {
 
3582   var lower48 = d3.geo.albers();
 
3585   var alaska = d3.geo.conicEqualArea()
 
3588       .parallels([55, 65]);
 
3591   var hawaii = d3.geo.conicEqualArea()
 
3594       .parallels([8, 18]);
 
3597       pointStream = {point: function(x, y) { point = [x, y]; }},
 
3602   function albersUsa(coordinates) {
 
3603     var x = coordinates[0], y = coordinates[1];
 
3605     (lower48Point(x, y), point)
 
3606         || (alaskaPoint(x, y), point)
 
3607         || hawaiiPoint(x, y);
 
3611   albersUsa.invert = function(coordinates) {
 
3612     var k = lower48.scale(),
 
3613         t = lower48.translate(),
 
3614         x = (coordinates[0] - t[0]) / k,
 
3615         y = (coordinates[1] - t[1]) / k;
 
3616     return (y >= .120 && y < .234 && x >= -.425 && x < -.214 ? alaska
 
3617         : y >= .166 && y < .234 && x >= -.214 && x < -.115 ? hawaii
 
3618         : lower48).invert(coordinates);
 
3621   // A naïve multi-projection stream.
 
3622   // The projections must have mutually exclusive clip regions on the sphere,
 
3623   // as this will avoid emitting interleaving lines and polygons.
 
3624   albersUsa.stream = function(stream) {
 
3625     var lower48Stream = lower48.stream(stream),
 
3626         alaskaStream = alaska.stream(stream),
 
3627         hawaiiStream = hawaii.stream(stream);
 
3629       point: function(x, y) {
 
3630         lower48Stream.point(x, y);
 
3631         alaskaStream.point(x, y);
 
3632         hawaiiStream.point(x, y);
 
3634       sphere: function() {
 
3635         lower48Stream.sphere();
 
3636         alaskaStream.sphere();
 
3637         hawaiiStream.sphere();
 
3639       lineStart: function() {
 
3640         lower48Stream.lineStart();
 
3641         alaskaStream.lineStart();
 
3642         hawaiiStream.lineStart();
 
3644       lineEnd: function() {
 
3645         lower48Stream.lineEnd();
 
3646         alaskaStream.lineEnd();
 
3647         hawaiiStream.lineEnd();
 
3649       polygonStart: function() {
 
3650         lower48Stream.polygonStart();
 
3651         alaskaStream.polygonStart();
 
3652         hawaiiStream.polygonStart();
 
3654       polygonEnd: function() {
 
3655         lower48Stream.polygonEnd();
 
3656         alaskaStream.polygonEnd();
 
3657         hawaiiStream.polygonEnd();
 
3662   albersUsa.precision = function(_) {
 
3663     if (!arguments.length) return lower48.precision();
 
3664     lower48.precision(_);
 
3665     alaska.precision(_);
 
3666     hawaii.precision(_);
 
3670   albersUsa.scale = function(_) {
 
3671     if (!arguments.length) return lower48.scale();
 
3673     alaska.scale(_ * .35);
 
3675     return albersUsa.translate(lower48.translate());
 
3678   albersUsa.translate = function(_) {
 
3679     if (!arguments.length) return lower48.translate();
 
3680     var k = lower48.scale(), x = +_[0], y = +_[1];
 
3682     lower48Point = lower48
 
3684         .clipExtent([[x - .455 * k, y - .238 * k], [x + .455 * k, y + .238 * k]])
 
3685         .stream(pointStream).point;
 
3687     alaskaPoint = alaska
 
3688         .translate([x - .307 * k, y + .201 * k])
 
3689         .clipExtent([[x - .425 * k + ε, y + .120 * k + ε], [x - .214 * k - ε, y + .234 * k - ε]])
 
3690         .stream(pointStream).point;
 
3692     hawaiiPoint = hawaii
 
3693         .translate([x - .205 * k, y + .212 * k])
 
3694         .clipExtent([[x - .214 * k + ε, y + .166 * k + ε], [x - .115 * k - ε, y + .234 * k - ε]])
 
3695         .stream(pointStream).point;
 
3700   return albersUsa.scale(1070);
 
3703 d3.geo.bounds = (function() {
 
3704   var λ0, φ0, λ1, φ1, // bounds
 
3705       λ_, // previous λ-coordinate
 
3706       λ__, φ__, // first point
 
3707       p0, // previous 3D point
 
3714     lineStart: lineStart,
 
3717     polygonStart: function() {
 
3718       bound.point = ringPoint;
 
3719       bound.lineStart = ringStart;
 
3720       bound.lineEnd = ringEnd;
 
3722       d3_geo_area.polygonStart();
 
3724     polygonEnd: function() {
 
3725       d3_geo_area.polygonEnd();
 
3726       bound.point = point;
 
3727       bound.lineStart = lineStart;
 
3728       bound.lineEnd = lineEnd;
 
3729       if (d3_geo_areaRingSum < 0) λ0 = -(λ1 = 180), φ0 = -(φ1 = 90);
 
3730       else if (dλSum > ε) φ1 = 90;
 
3731       else if (dλSum < -ε) φ0 = -90;
 
3732       range[0] = λ0, range[1] = λ1;
 
3736   function point(λ, φ) {
 
3737     ranges.push(range = [λ0 = λ, λ1 = λ]);
 
3742   function linePoint(λ, φ) {
 
3743     var p = d3_geo_cartesian([λ * d3_radians, φ * d3_radians]);
 
3745       var normal = d3_geo_cartesianCross(p0, p),
 
3746           equatorial = [normal[1], -normal[0], 0],
 
3747           inflection = d3_geo_cartesianCross(equatorial, normal);
 
3748       d3_geo_cartesianNormalize(inflection);
 
3749       inflection = d3_geo_spherical(inflection);
 
3751           s = dλ > 0 ? 1 : -1,
 
3752           λi = inflection[0] * d3_degrees * s,
 
3753           antimeridian = abs(dλ) > 180;
 
3754       if (antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
 
3755         var φi = inflection[1] * d3_degrees;
 
3756         if (φi > φ1) φ1 = φi;
 
3757       } else if (λi = (λi + 360) % 360 - 180, antimeridian ^ (s * λ_ < λi && λi < s * λ)) {
 
3758         var φi = -inflection[1] * d3_degrees;
 
3759         if (φi < φ0) φ0 = φi;
 
3766           if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
 
3768           if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
 
3776             if (angle(λ0, λ) > angle(λ0, λ1)) λ1 = λ;
 
3778             if (angle(λ, λ1) > angle(λ0, λ1)) λ0 = λ;
 
3788   function lineStart() { bound.point = linePoint; }
 
3789   function lineEnd() {
 
3790     range[0] = λ0, range[1] = λ1;
 
3791     bound.point = point;
 
3795   function ringPoint(λ, φ) {
 
3798       dλSum += abs(dλ) > 180 ? dλ + (dλ > 0 ? 360 : -360) : dλ;
 
3799     } else λ__ = λ, φ__ = φ;
 
3800     d3_geo_area.point(λ, φ);
 
3804   function ringStart() {
 
3805     d3_geo_area.lineStart();
 
3808   function ringEnd() {
 
3809     ringPoint(λ__, φ__);
 
3810     d3_geo_area.lineEnd();
 
3811     if (abs(dλSum) > ε) λ0 = -(λ1 = 180);
 
3812     range[0] = λ0, range[1] = λ1;
 
3816   // Finds the left-right distance between two longitudes.
 
3817   // This is almost the same as (λ1 - λ0 + 360°) % 360°, except that we want
 
3818   // the distance between ±180° to be 360°.
 
3819   function angle(λ0, λ1) { return (λ1 -= λ0) < 0 ? λ1 + 360 : λ1; }
 
3821   function compareRanges(a, b) { return a[0] - b[0]; }
 
3823   function withinRange(x, range) {
 
3824     return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
 
3827   return function(feature) {
 
3828     φ1 = λ1 = -(λ0 = φ0 = Infinity);
 
3831     d3.geo.stream(feature, bound);
 
3833     var n = ranges.length;
 
3835       // First, sort ranges by their minimum longitudes.
 
3836       ranges.sort(compareRanges);
 
3838       // Then, merge any ranges that overlap.
 
3839       for (var i = 1, a = ranges[0], b, merged = [a]; i < n; ++i) {
 
3841         if (withinRange(b[0], a) || withinRange(b[1], a)) {
 
3842           if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
 
3843           if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
 
3849       // Finally, find the largest gap between the merged ranges.
 
3850       // The final bounding box will be the inverse of this gap.
 
3851       var best = -Infinity, dλ;
 
3852       for (var n = merged.length - 1, i = 0, a = merged[n], b; i <= n; a = b, ++i) {
 
3854         if ((dλ = angle(a[1], b[0])) > best) best = dλ, λ0 = b[0], λ1 = a[1];
 
3857     ranges = range = null;
 
3859     return λ0 === Infinity || φ0 === Infinity
 
3860         ? [[NaN, NaN], [NaN, NaN]]
 
3861         : [[λ0, φ0], [λ1, φ1]];
 
3865 d3.geo.centroid = function(object) {
 
3866   d3_geo_centroidW0 = d3_geo_centroidW1 =
 
3867   d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 =
 
3868   d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 =
 
3869   d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
 
3870   d3.geo.stream(object, d3_geo_centroid);
 
3872   var x = d3_geo_centroidX2,
 
3873       y = d3_geo_centroidY2,
 
3874       z = d3_geo_centroidZ2,
 
3875       m = x * x + y * y + z * z;
 
3877   // If the area-weighted centroid is undefined, fall back to length-weighted centroid.
 
3879     x = d3_geo_centroidX1, y = d3_geo_centroidY1, z = d3_geo_centroidZ1;
 
3880     // If the feature has zero length, fall back to arithmetic mean of point vectors.
 
3881     if (d3_geo_centroidW1 < ε) x = d3_geo_centroidX0, y = d3_geo_centroidY0, z = d3_geo_centroidZ0;
 
3882     m = x * x + y * y + z * z;
 
3883     // If the feature still has an undefined centroid, then return.
 
3884     if (m < ε2) return [NaN, NaN];
 
3887   return [Math.atan2(y, x) * d3_degrees, d3_asin(z / Math.sqrt(m)) * d3_degrees];
 
3890 var d3_geo_centroidW0,
 
3902 var d3_geo_centroid = {
 
3904   point: d3_geo_centroidPoint,
 
3905   lineStart: d3_geo_centroidLineStart,
 
3906   lineEnd: d3_geo_centroidLineEnd,
 
3907   polygonStart: function() {
 
3908     d3_geo_centroid.lineStart = d3_geo_centroidRingStart;
 
3910   polygonEnd: function() {
 
3911     d3_geo_centroid.lineStart = d3_geo_centroidLineStart;
 
3915 // Arithmetic mean of Cartesian vectors.
 
3916 function d3_geo_centroidPoint(λ, φ) {
 
3918   var cosφ = Math.cos(φ *= d3_radians);
 
3919   d3_geo_centroidPointXYZ(cosφ * Math.cos(λ), cosφ * Math.sin(λ), Math.sin(φ));
 
3922 function d3_geo_centroidPointXYZ(x, y, z) {
 
3923   ++d3_geo_centroidW0;
 
3924   d3_geo_centroidX0 += (x - d3_geo_centroidX0) / d3_geo_centroidW0;
 
3925   d3_geo_centroidY0 += (y - d3_geo_centroidY0) / d3_geo_centroidW0;
 
3926   d3_geo_centroidZ0 += (z - d3_geo_centroidZ0) / d3_geo_centroidW0;
 
3929 function d3_geo_centroidLineStart() {
 
3930   var x0, y0, z0; // previous point
 
3932   d3_geo_centroid.point = function(λ, φ) {
 
3934     var cosφ = Math.cos(φ *= d3_radians);
 
3935     x0 = cosφ * Math.cos(λ);
 
3936     y0 = cosφ * Math.sin(λ);
 
3938     d3_geo_centroid.point = nextPoint;
 
3939     d3_geo_centroidPointXYZ(x0, y0, z0);
 
3942   function nextPoint(λ, φ) {
 
3944     var cosφ = Math.cos(φ *= d3_radians),
 
3945         x = cosφ * Math.cos(λ),
 
3946         y = cosφ * Math.sin(λ),
 
3949           Math.sqrt((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w),
 
3950           x0 * x + y0 * y + z0 * z);
 
3951     d3_geo_centroidW1 += w;
 
3952     d3_geo_centroidX1 += w * (x0 + (x0 = x));
 
3953     d3_geo_centroidY1 += w * (y0 + (y0 = y));
 
3954     d3_geo_centroidZ1 += w * (z0 + (z0 = z));
 
3955     d3_geo_centroidPointXYZ(x0, y0, z0);
 
3959 function d3_geo_centroidLineEnd() {
 
3960   d3_geo_centroid.point = d3_geo_centroidPoint;
 
3963 // See J. E. Brock, The Inertia Tensor for a Spherical Triangle,
 
3964 // J. Applied Mechanics 42, 239 (1975).
 
3965 function d3_geo_centroidRingStart() {
 
3966   var λ00, φ00, // first point
 
3967       x0, y0, z0; // previous point
 
3969   d3_geo_centroid.point = function(λ, φ) {
 
3971     d3_geo_centroid.point = nextPoint;
 
3973     var cosφ = Math.cos(φ *= d3_radians);
 
3974     x0 = cosφ * Math.cos(λ);
 
3975     y0 = cosφ * Math.sin(λ);
 
3977     d3_geo_centroidPointXYZ(x0, y0, z0);
 
3980   d3_geo_centroid.lineEnd = function() {
 
3981     nextPoint(λ00, φ00);
 
3982     d3_geo_centroid.lineEnd = d3_geo_centroidLineEnd;
 
3983     d3_geo_centroid.point = d3_geo_centroidPoint;
 
3986   function nextPoint(λ, φ) {
 
3988     var cosφ = Math.cos(φ *= d3_radians),
 
3989         x = cosφ * Math.cos(λ),
 
3990         y = cosφ * Math.sin(λ),
 
3992         cx = y0 * z - z0 * y,
 
3993         cy = z0 * x - x0 * z,
 
3994         cz = x0 * y - y0 * x,
 
3995         m = Math.sqrt(cx * cx + cy * cy + cz * cz),
 
3996         u = x0 * x + y0 * y + z0 * z,
 
3997         v = m && -d3_acos(u) / m, // area weight
 
3998         w = Math.atan2(m, u); // line weight
 
3999     d3_geo_centroidX2 += v * cx;
 
4000     d3_geo_centroidY2 += v * cy;
 
4001     d3_geo_centroidZ2 += v * cz;
 
4002     d3_geo_centroidW1 += w;
 
4003     d3_geo_centroidX1 += w * (x0 + (x0 = x));
 
4004     d3_geo_centroidY1 += w * (y0 + (y0 = y));
 
4005     d3_geo_centroidZ1 += w * (z0 + (z0 = z));
 
4006     d3_geo_centroidPointXYZ(x0, y0, z0);
 
4010 // TODO Unify this code with d3.geom.polygon area?
 
4012 var d3_geo_pathAreaSum, d3_geo_pathAreaPolygon, d3_geo_pathArea = {
 
4017   // Only count area for polygon rings.
 
4018   polygonStart: function() {
 
4019     d3_geo_pathAreaPolygon = 0;
 
4020     d3_geo_pathArea.lineStart = d3_geo_pathAreaRingStart;
 
4022   polygonEnd: function() {
 
4023     d3_geo_pathArea.lineStart = d3_geo_pathArea.lineEnd = d3_geo_pathArea.point = d3_noop;
 
4024     d3_geo_pathAreaSum += abs(d3_geo_pathAreaPolygon / 2);
 
4028 function d3_geo_pathAreaRingStart() {
 
4029   var x00, y00, x0, y0;
 
4031   // For the first point, …
 
4032   d3_geo_pathArea.point = function(x, y) {
 
4033     d3_geo_pathArea.point = nextPoint;
 
4034     x00 = x0 = x, y00 = y0 = y;
 
4037   // For subsequent points, …
 
4038   function nextPoint(x, y) {
 
4039     d3_geo_pathAreaPolygon += y0 * x - x0 * y;
 
4043   // For the last point, return to the start.
 
4044   d3_geo_pathArea.lineEnd = function() {
 
4045     nextPoint(x00, y00);
 
4049 var d3_geo_pathBoundsX0,
 
4050     d3_geo_pathBoundsY0,
 
4051     d3_geo_pathBoundsX1,
 
4052     d3_geo_pathBoundsY1;
 
4054 var d3_geo_pathBounds = {
 
4055   point: d3_geo_pathBoundsPoint,
 
4058   polygonStart: d3_noop,
 
4062 function d3_geo_pathBoundsPoint(x, y) {
 
4063   if (x < d3_geo_pathBoundsX0) d3_geo_pathBoundsX0 = x;
 
4064   if (x > d3_geo_pathBoundsX1) d3_geo_pathBoundsX1 = x;
 
4065   if (y < d3_geo_pathBoundsY0) d3_geo_pathBoundsY0 = y;
 
4066   if (y > d3_geo_pathBoundsY1) d3_geo_pathBoundsY1 = y;
 
4068 function d3_geo_pathBuffer() {
 
4069   var pointCircle = d3_geo_pathBufferCircle(4.5),
 
4075     // While inside a line, override point to moveTo then lineTo.
 
4076     lineStart: function() { stream.point = pointLineStart; },
 
4079     // While inside a polygon, override lineEnd to closePath.
 
4080     polygonStart: function() { stream.lineEnd = lineEndPolygon; },
 
4081     polygonEnd: function() { stream.lineEnd = lineEnd; stream.point = point; },
 
4083     pointRadius: function(_) {
 
4084       pointCircle = d3_geo_pathBufferCircle(_);
 
4088     result: function() {
 
4089       if (buffer.length) {
 
4090         var result = buffer.join("");
 
4097   function point(x, y) {
 
4098     buffer.push("M", x, ",", y, pointCircle);
 
4101   function pointLineStart(x, y) {
 
4102     buffer.push("M", x, ",", y);
 
4103     stream.point = pointLine;
 
4106   function pointLine(x, y) {
 
4107     buffer.push("L", x, ",", y);
 
4110   function lineEnd() {
 
4111     stream.point = point;
 
4114   function lineEndPolygon() {
 
4121 function d3_geo_pathBufferCircle(radius) {
 
4122   return "m0," + radius
 
4123       + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius
 
4124       + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius
 
4128 // TODO Unify this code with d3.geom.polygon centroid?
 
4129 // TODO Enforce positive area for exterior, negative area for interior?
 
4131 var d3_geo_pathCentroid = {
 
4132   point: d3_geo_pathCentroidPoint,
 
4134   // For lines, weight by length.
 
4135   lineStart: d3_geo_pathCentroidLineStart,
 
4136   lineEnd: d3_geo_pathCentroidLineEnd,
 
4138   // For polygons, weight by area.
 
4139   polygonStart: function() {
 
4140     d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidRingStart;
 
4142   polygonEnd: function() {
 
4143     d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
 
4144     d3_geo_pathCentroid.lineStart = d3_geo_pathCentroidLineStart;
 
4145     d3_geo_pathCentroid.lineEnd = d3_geo_pathCentroidLineEnd;
 
4149 function d3_geo_pathCentroidPoint(x, y) {
 
4150   d3_geo_centroidX0 += x;
 
4151   d3_geo_centroidY0 += y;
 
4152   ++d3_geo_centroidZ0;
 
4155 function d3_geo_pathCentroidLineStart() {
 
4158   d3_geo_pathCentroid.point = function(x, y) {
 
4159     d3_geo_pathCentroid.point = nextPoint;
 
4160     d3_geo_pathCentroidPoint(x0 = x, y0 = y);
 
4163   function nextPoint(x, y) {
 
4164     var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
 
4165     d3_geo_centroidX1 += z * (x0 + x) / 2;
 
4166     d3_geo_centroidY1 += z * (y0 + y) / 2;
 
4167     d3_geo_centroidZ1 += z;
 
4168     d3_geo_pathCentroidPoint(x0 = x, y0 = y);
 
4172 function d3_geo_pathCentroidLineEnd() {
 
4173   d3_geo_pathCentroid.point = d3_geo_pathCentroidPoint;
 
4176 function d3_geo_pathCentroidRingStart() {
 
4177   var x00, y00, x0, y0;
 
4179   // For the first point, …
 
4180   d3_geo_pathCentroid.point = function(x, y) {
 
4181     d3_geo_pathCentroid.point = nextPoint;
 
4182     d3_geo_pathCentroidPoint(x00 = x0 = x, y00 = y0 = y);
 
4185   // For subsequent points, …
 
4186   function nextPoint(x, y) {
 
4187     var dx = x - x0, dy = y - y0, z = Math.sqrt(dx * dx + dy * dy);
 
4188     d3_geo_centroidX1 += z * (x0 + x) / 2;
 
4189     d3_geo_centroidY1 += z * (y0 + y) / 2;
 
4190     d3_geo_centroidZ1 += z;
 
4192     z = y0 * x - x0 * y;
 
4193     d3_geo_centroidX2 += z * (x0 + x);
 
4194     d3_geo_centroidY2 += z * (y0 + y);
 
4195     d3_geo_centroidZ2 += z * 3;
 
4196     d3_geo_pathCentroidPoint(x0 = x, y0 = y);
 
4199   // For the last point, return to the start.
 
4200   d3_geo_pathCentroid.lineEnd = function() {
 
4201     nextPoint(x00, y00);
 
4205 function d3_geo_pathContext(context) {
 
4206   var pointRadius = 4.5;
 
4211     // While inside a line, override point to moveTo then lineTo.
 
4212     lineStart: function() { stream.point = pointLineStart; },
 
4215     // While inside a polygon, override lineEnd to closePath.
 
4216     polygonStart: function() { stream.lineEnd = lineEndPolygon; },
 
4217     polygonEnd: function() { stream.lineEnd = lineEnd; stream.point = point; },
 
4219     pointRadius: function(_) {
 
4227   function point(x, y) {
 
4228     context.moveTo(x + pointRadius, y);
 
4229     context.arc(x, y, pointRadius, 0, τ);
 
4232   function pointLineStart(x, y) {
 
4233     context.moveTo(x, y);
 
4234     stream.point = pointLine;
 
4237   function pointLine(x, y) {
 
4238     context.lineTo(x, y);
 
4241   function lineEnd() {
 
4242     stream.point = point;
 
4245   function lineEndPolygon() {
 
4246     context.closePath();
 
4252 function d3_geo_resample(project) {
 
4253   var δ2 = .5, // precision, px²
 
4254       cosMinDistance = Math.cos(30 * d3_radians), // cos(minimum angular distance)
 
4257   function resample(stream) {
 
4258     return (maxDepth ? resampleRecursive : resampleNone)(stream);
 
4261   function resampleNone(stream) {
 
4262     return d3_geo_transformPoint(stream, function(x, y) {
 
4264       stream.point(x[0], x[1]);
 
4268   function resampleRecursive(stream) {
 
4269     var λ00, φ00, x00, y00, a00, b00, c00, // first point
 
4270         λ0, x0, y0, a0, b0, c0; // previous point
 
4274       lineStart: lineStart,
 
4276       polygonStart: function() { stream.polygonStart(); resample.lineStart = ringStart; },
 
4277       polygonEnd: function() { stream.polygonEnd(); resample.lineStart = lineStart; }
 
4280     function point(x, y) {
 
4282       stream.point(x[0], x[1]);
 
4285     function lineStart() {
 
4287       resample.point = linePoint;
 
4291     function linePoint(λ, φ) {
 
4292       var c = d3_geo_cartesian([λ, φ]), p = project(λ, φ);
 
4293       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);
 
4294       stream.point(x0, y0);
 
4297     function lineEnd() {
 
4298       resample.point = point;
 
4302     function ringStart() {
 
4304       resample.point = ringPoint;
 
4305       resample.lineEnd = ringEnd;
 
4308     function ringPoint(λ, φ) {
 
4309       linePoint(λ00 = λ, φ00 = φ), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
 
4310       resample.point = linePoint;
 
4313     function ringEnd() {
 
4314       resampleLineTo(x0, y0, λ0, a0, b0, c0, x00, y00, λ00, a00, b00, c00, maxDepth, stream);
 
4315       resample.lineEnd = lineEnd;
 
4322   function resampleLineTo(x0, y0, λ0, a0, b0, c0, x1, y1, λ1, a1, b1, c1, depth, stream) {
 
4325         d2 = dx * dx + dy * dy;
 
4326     if (d2 > 4 * δ2 && depth--) {
 
4330           m = Math.sqrt(a * a + b * b + c * c),
 
4331           φ2 = Math.asin(c /= m),
 
4332           λ2 = abs(abs(c) - 1) < ε || abs(λ0 - λ1) < ε ? (λ0 + λ1) / 2 : Math.atan2(b, a),
 
4333           p = project(λ2, φ2),
 
4338           dz = dy * dx2 - dx * dy2;
 
4339       if (dz * dz / d2 > δ2 // perpendicular projected distance
 
4340           || abs((dx * dx2 + dy * dy2) / d2 - .5) > .3 // midpoint close to an end
 
4341           || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { // angular distance
 
4342         resampleLineTo(x0, y0, λ0, a0, b0, c0, x2, y2, λ2, a /= m, b /= m, c, depth, stream);
 
4343         stream.point(x2, y2);
 
4344         resampleLineTo(x2, y2, λ2, a, b, c, x1, y1, λ1, a1, b1, c1, depth, stream);
 
4349   resample.precision = function(_) {
 
4350     if (!arguments.length) return Math.sqrt(δ2);
 
4351     maxDepth = (δ2 = _ * _) > 0 && 16;
 
4358 d3.geo.path = function() {
 
4359   var pointRadius = 4.5,
 
4366   function path(object) {
 
4368       if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
 
4369       if (!cacheStream || !cacheStream.valid) cacheStream = projectStream(contextStream);
 
4370       d3.geo.stream(object, cacheStream);
 
4372     return contextStream.result();
 
4375   path.area = function(object) {
 
4376     d3_geo_pathAreaSum = 0;
 
4377     d3.geo.stream(object, projectStream(d3_geo_pathArea));
 
4378     return d3_geo_pathAreaSum;
 
4381   path.centroid = function(object) {
 
4382     d3_geo_centroidX0 = d3_geo_centroidY0 = d3_geo_centroidZ0 =
 
4383     d3_geo_centroidX1 = d3_geo_centroidY1 = d3_geo_centroidZ1 =
 
4384     d3_geo_centroidX2 = d3_geo_centroidY2 = d3_geo_centroidZ2 = 0;
 
4385     d3.geo.stream(object, projectStream(d3_geo_pathCentroid));
 
4386     return d3_geo_centroidZ2 ? [d3_geo_centroidX2 / d3_geo_centroidZ2, d3_geo_centroidY2 / d3_geo_centroidZ2]
 
4387         : d3_geo_centroidZ1 ? [d3_geo_centroidX1 / d3_geo_centroidZ1, d3_geo_centroidY1 / d3_geo_centroidZ1]
 
4388         : d3_geo_centroidZ0 ? [d3_geo_centroidX0 / d3_geo_centroidZ0, d3_geo_centroidY0 / d3_geo_centroidZ0]
 
4392   path.bounds = function(object) {
 
4393     d3_geo_pathBoundsX1 = d3_geo_pathBoundsY1 = -(d3_geo_pathBoundsX0 = d3_geo_pathBoundsY0 = Infinity);
 
4394     d3.geo.stream(object, projectStream(d3_geo_pathBounds));
 
4395     return [[d3_geo_pathBoundsX0, d3_geo_pathBoundsY0], [d3_geo_pathBoundsX1, d3_geo_pathBoundsY1]];
 
4398   path.projection = function(_) {
 
4399     if (!arguments.length) return projection;
 
4400     projectStream = (projection = _) ? _.stream || d3_geo_pathProjectStream(_) : d3_identity;
 
4404   path.context = function(_) {
 
4405     if (!arguments.length) return context;
 
4406     contextStream = (context = _) == null ? new d3_geo_pathBuffer : new d3_geo_pathContext(_);
 
4407     if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
 
4411   path.pointRadius = function(_) {
 
4412     if (!arguments.length) return pointRadius;
 
4413     pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_);
 
4422   return path.projection(d3.geo.albersUsa()).context(null);
 
4425 function d3_geo_pathProjectStream(project) {
 
4426   var resample = d3_geo_resample(function(x, y) { return project([x * d3_degrees, y * d3_degrees]); });
 
4427   return function(stream) { return d3_geo_projectionRadians(resample(stream)); };
 
4430 d3.geo.transform = function(methods) {
 
4432     stream: function(stream) {
 
4433       var transform = new d3_geo_transform(stream);
 
4434       for (var k in methods) transform[k] = methods[k];
 
4440 function d3_geo_transform(stream) {
 
4441   this.stream = stream;
 
4444 d3_geo_transform.prototype = {
 
4445   point: function(x, y) { this.stream.point(x, y); },
 
4446   sphere: function() { this.stream.sphere(); },
 
4447   lineStart: function() { this.stream.lineStart(); },
 
4448   lineEnd: function() { this.stream.lineEnd(); },
 
4449   polygonStart: function() { this.stream.polygonStart(); },
 
4450   polygonEnd: function() { this.stream.polygonEnd(); }
 
4453 function d3_geo_transformPoint(stream, point) {
 
4456     sphere: function() { stream.sphere(); },
 
4457     lineStart: function() { stream.lineStart(); },
 
4458     lineEnd: function() { stream.lineEnd(); },
 
4459     polygonStart: function() { stream.polygonStart(); },
 
4460     polygonEnd: function() { stream.polygonEnd(); },
 
4464 d3.geo.projection = d3_geo_projection;
 
4465 d3.geo.projectionMutator = d3_geo_projectionMutator;
 
4467 function d3_geo_projection(project) {
 
4468   return d3_geo_projectionMutator(function() { return project; })();
 
4471 function d3_geo_projectionMutator(projectAt) {
 
4475       projectResample = d3_geo_resample(function(x, y) { x = project(x, y); return [x[0] * k + δx, δy - x[1] * k]; }),
 
4477       x = 480, y = 250, // translate
 
4478       λ = 0, φ = 0, // center
 
4479       δλ = 0, δφ = 0, δγ = 0, // rotate
 
4481       preclip = d3_geo_clipAntimeridian,
 
4482       postclip = d3_identity,
 
4487   function projection(point) {
 
4488     point = projectRotate(point[0] * d3_radians, point[1] * d3_radians);
 
4489     return [point[0] * k + δx, δy - point[1] * k];
 
4492   function invert(point) {
 
4493     point = projectRotate.invert((point[0] - δx) / k, (δy - point[1]) / k);
 
4494     return point && [point[0] * d3_degrees, point[1] * d3_degrees];
 
4497   projection.stream = function(output) {
 
4498     if (stream) stream.valid = false;
 
4499     stream = d3_geo_projectionRadians(preclip(rotate, projectResample(postclip(output))));
 
4500     stream.valid = true; // allow caching by d3.geo.path
 
4504   projection.clipAngle = function(_) {
 
4505     if (!arguments.length) return clipAngle;
 
4506     preclip = _ == null ? (clipAngle = _, d3_geo_clipAntimeridian) : d3_geo_clipCircle((clipAngle = +_) * d3_radians);
 
4507     return invalidate();
 
4510   projection.clipExtent = function(_) {
 
4511     if (!arguments.length) return clipExtent;
 
4513     postclip = _ ? d3_geo_clipExtent(_[0][0], _[0][1], _[1][0], _[1][1]) : d3_identity;
 
4514     return invalidate();
 
4517   projection.scale = function(_) {
 
4518     if (!arguments.length) return k;
 
4523   projection.translate = function(_) {
 
4524     if (!arguments.length) return [x, y];
 
4530   projection.center = function(_) {
 
4531     if (!arguments.length) return [λ * d3_degrees, φ * d3_degrees];
 
4532     λ = _[0] % 360 * d3_radians;
 
4533     φ = _[1] % 360 * d3_radians;
 
4537   projection.rotate = function(_) {
 
4538     if (!arguments.length) return [δλ * d3_degrees, δφ * d3_degrees, δγ * d3_degrees];
 
4539     δλ = _[0] % 360 * d3_radians;
 
4540     δφ = _[1] % 360 * d3_radians;
 
4541     δγ = _.length > 2 ? _[2] % 360 * d3_radians : 0;
 
4545   d3.rebind(projection, projectResample, "precision");
 
4548     projectRotate = d3_geo_compose(rotate = d3_geo_rotation(δλ, δφ, δγ), project);
 
4549     var center = project(λ, φ);
 
4550     δx = x - center[0] * k;
 
4551     δy = y + center[1] * k;
 
4552     return invalidate();
 
4555   function invalidate() {
 
4556     if (stream) stream.valid = false, stream = null;
 
4561     project = projectAt.apply(this, arguments);
 
4562     projection.invert = project.invert && invert;
 
4567 function d3_geo_projectionRadians(stream) {
 
4568   return d3_geo_transformPoint(stream, function(x, y) {
 
4569     stream.point(x * d3_radians, y * d3_radians);
 
4573 function d3_geo_mercator(λ, φ) {
 
4574   return [λ, Math.log(Math.tan(π / 4 + φ / 2))];
 
4577 d3_geo_mercator.invert = function(x, y) {
 
4578   return [x, 2 * Math.atan(Math.exp(y)) - halfπ];
 
4581 function d3_geo_mercatorProjection(project) {
 
4582   var m = d3_geo_projection(project),
 
4584       translate = m.translate,
 
4585       clipExtent = m.clipExtent,
 
4588   m.scale = function() {
 
4589     var v = scale.apply(m, arguments);
 
4590     return v === m ? (clipAuto ? m.clipExtent(null) : m) : v;
 
4593   m.translate = function() {
 
4594     var v = translate.apply(m, arguments);
 
4595     return v === m ? (clipAuto ? m.clipExtent(null) : m) : v;
 
4598   m.clipExtent = function(_) {
 
4599     var v = clipExtent.apply(m, arguments);
 
4601       if (clipAuto = _ == null) {
 
4602         var k = π * scale(), t = translate();
 
4603         clipExtent([[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]]);
 
4605     } else if (clipAuto) {
 
4611   return m.clipExtent(null);
 
4614 (d3.geo.mercator = function() {
 
4615   return d3_geo_mercatorProjection(d3_geo_mercator);
 
4616 }).raw = d3_geo_mercator;
 
4619 d3.geom.polygon = function(coordinates) {
 
4620   d3_subclass(coordinates, d3_geom_polygonPrototype);
 
4624 var d3_geom_polygonPrototype = d3.geom.polygon.prototype = [];
 
4626 d3_geom_polygonPrototype.area = function() {
 
4636     area += a[1] * b[0] - a[0] * b[1];
 
4642 d3_geom_polygonPrototype.centroid = function(k) {
 
4651   if (!arguments.length) k = -1 / (6 * this.area());
 
4656     c = a[0] * b[1] - b[0] * a[1];
 
4657     x += (a[0] + b[0]) * c;
 
4658     y += (a[1] + b[1]) * c;
 
4661   return [x * k, y * k];
 
4664 // The Sutherland-Hodgman clipping algorithm.
 
4665 // Note: requires the clip polygon to be counterclockwise and convex.
 
4666 d3_geom_polygonPrototype.clip = function(subject) {
 
4668       closed = d3_geom_polygonClosed(subject),
 
4670       n = this.length - d3_geom_polygonClosed(this),
 
4679     input = subject.slice();
 
4682     c = input[(m = input.length - closed) - 1];
 
4686       if (d3_geom_polygonInside(d, a, b)) {
 
4687         if (!d3_geom_polygonInside(c, a, b)) {
 
4688           subject.push(d3_geom_polygonIntersect(c, d, a, b));
 
4691       } else if (d3_geom_polygonInside(c, a, b)) {
 
4692         subject.push(d3_geom_polygonIntersect(c, d, a, b));
 
4696     if (closed) subject.push(subject[0]);
 
4703 function d3_geom_polygonInside(p, a, b) {
 
4704   return (b[0] - a[0]) * (p[1] - a[1]) < (b[1] - a[1]) * (p[0] - a[0]);
 
4707 // Intersect two infinite lines cd and ab.
 
4708 function d3_geom_polygonIntersect(c, d, a, b) {
 
4709   var x1 = c[0], x3 = a[0], x21 = d[0] - x1, x43 = b[0] - x3,
 
4710       y1 = c[1], y3 = a[1], y21 = d[1] - y1, y43 = b[1] - y3,
 
4711       ua = (x43 * (y1 - y3) - y43 * (x1 - x3)) / (y43 * x21 - x43 * y21);
 
4712   return [x1 + ua * x21, y1 + ua * y21];
 
4715 // Returns true if the polygon is closed.
 
4716 function d3_geom_polygonClosed(coordinates) {
 
4717   var a = coordinates[0],
 
4718       b = coordinates[coordinates.length - 1];
 
4719   return !(a[0] - b[0] || a[1] - b[1]);
 
4721 function d3_geom_pointX(d) {
 
4725 function d3_geom_pointY(d) {
 
4730  * Computes the 2D convex hull of a set of points using the monotone chain
 
4732  * http://en.wikibooks.org/wiki/Algorithm_Implementation/Geometry/Convex_hull/Monotone_chain)
 
4734  * The runtime of this algorithm is O(n log n), where n is the number of input
 
4735  * points. However in practice it outperforms other O(n log n) hulls.
 
4737  * @param vertices [[x1, y1], [x2, y2], ...]
 
4738  * @returns polygon [[x1, y1], [x2, y2], ...]
 
4740 d3.geom.hull = function(vertices) {
 
4741   var x = d3_geom_pointX,
 
4744   if (arguments.length) return hull(vertices);
 
4746   function hull(data) {
 
4747     // Hull of < 3 points is not well-defined
 
4748     if (data.length < 3) return [];
 
4750     var fx = d3_functor(x),
 
4754         points = [], // of the form [[x0, y0, 0], ..., [xn, yn, n]]
 
4757     for (i = 0 ; i < n; i++) {
 
4758       points.push([+fx.call(this, data[i], i), +fy.call(this, data[i], i), i]);
 
4761     // sort ascending by x-coord first, y-coord second
 
4762     points.sort(d3_geom_hullOrder);
 
4764     // we flip bottommost points across y axis so we can use the upper hull routine on both
 
4765     for (i = 0; i < n; i++) flippedPoints.push([points[i][0], -points[i][1]]);
 
4767     var upper = d3_geom_hullUpper(points),
 
4768         lower = d3_geom_hullUpper(flippedPoints);
 
4770     // construct the polygon, removing possible duplicate endpoints
 
4771     var skipLeft = lower[0] === upper[0],
 
4772         skipRight  = lower[lower.length - 1] === upper[upper.length - 1],
 
4775     // add upper hull in r->l order
 
4776     // then add lower hull in l->r order
 
4777     for (i = upper.length - 1; i >= 0; --i) polygon.push(data[points[upper[i]][2]]);
 
4778     for (i = +skipLeft; i < lower.length - skipRight; ++i) polygon.push(data[points[lower[i]][2]]);
 
4783   hull.x = function(_) {
 
4784     return arguments.length ? (x = _, hull) : x;
 
4787   hull.y = function(_) {
 
4788     return arguments.length ? (y = _, hull) : y;
 
4794 // finds the 'upper convex hull' (see wiki link above)
 
4795 // assumes points arg has >=3 elements, is sorted by x, unique in y
 
4796 // returns array of indices into points in left to right order
 
4797 function d3_geom_hullUpper(points) {
 
4798   var n = points.length,
 
4800       hs = 2; // hull size
 
4802   for (var i = 2; i < n; i++) {
 
4803     while (hs > 1 && d3_cross2d(points[hull[hs-2]], points[hull[hs-1]], points[i]) <= 0) --hs;
 
4807   // we slice to make sure that the points we 'popped' from hull don't stay behind
 
4808   return hull.slice(0, hs);
 
4811 // comparator for ascending sort by x-coord first, y-coord second
 
4812 function d3_geom_hullOrder(a, b) {
 
4813   return a[0] - b[0] || a[1] - b[1];
 
4815 // import "../transition/transition";
 
4817 d3_selectionPrototype.transition = function(name) {
 
4818   var id = d3_transitionInheritId || ++d3_transitionId,
 
4819       ns = d3_transitionNamespace(name),
 
4823       transition = d3_transitionInherit || {time: Date.now(), ease: d3_ease_cubicInOut, delay: 0, duration: 250};
 
4825   for (var j = -1, m = this.length; ++j < m;) {
 
4826     subgroups.push(subgroup = []);
 
4827     for (var group = this[j], i = -1, n = group.length; ++i < n;) {
 
4828       if (node = group[i]) d3_transitionNode(node, i, ns, id, transition);
 
4829       subgroup.push(node);
 
4833   return d3_transition(subgroups, ns, id);
 
4835 // import "../transition/transition";
 
4837 // TODO Interrupt transitions for all namespaces?
 
4838 d3_selectionPrototype.interrupt = function(name) {
 
4839   return this.each(name == null
 
4840       ? d3_selection_interrupt
 
4841       : d3_selection_interruptNS(d3_transitionNamespace(name)));
 
4844 var d3_selection_interrupt = d3_selection_interruptNS(d3_transitionNamespace());
 
4846 function d3_selection_interruptNS(ns) {
 
4849     if ((lock = this[ns]) && (active = lock[lock.active])) {
 
4850       if (--lock.count) delete lock[lock.active];
 
4851       else delete this[ns];
 
4853       active.event && active.event.interrupt.call(this, this.__data__, active.index);
 
4858 function d3_transition(groups, ns, id) {
 
4859   d3_subclass(groups, d3_transitionPrototype);
 
4862   groups.namespace = ns;
 
4868 var d3_transitionPrototype = [],
 
4869     d3_transitionId = 0,
 
4870     d3_transitionInheritId,
 
4871     d3_transitionInherit;
 
4873 d3_transitionPrototype.call = d3_selectionPrototype.call;
 
4874 d3_transitionPrototype.empty = d3_selectionPrototype.empty;
 
4875 d3_transitionPrototype.node = d3_selectionPrototype.node;
 
4876 d3_transitionPrototype.size = d3_selectionPrototype.size;
 
4878 d3.transition = function(selection, name) {
 
4879   return selection && selection.transition
 
4880       ? (d3_transitionInheritId ? selection.transition(name) : selection)
 
4881       : d3.selection().transition(selection);
 
4884 d3.transition.prototype = d3_transitionPrototype;
 
4887 d3_transitionPrototype.select = function(selector) {
 
4889       ns = this.namespace,
 
4895   selector = d3_selection_selector(selector);
 
4897   for (var j = -1, m = this.length; ++j < m;) {
 
4898     subgroups.push(subgroup = []);
 
4899     for (var group = this[j], i = -1, n = group.length; ++i < n;) {
 
4900       if ((node = group[i]) && (subnode = selector.call(node, node.__data__, i, j))) {
 
4901         if ("__data__" in node) subnode.__data__ = node.__data__;
 
4902         d3_transitionNode(subnode, i, ns, id, node[ns][id]);
 
4903         subgroup.push(subnode);
 
4905         subgroup.push(null);
 
4910   return d3_transition(subgroups, ns, id);
 
4913 d3_transitionPrototype.selectAll = function(selector) {
 
4915       ns = this.namespace,
 
4923   selector = d3_selection_selectorAll(selector);
 
4925   for (var j = -1, m = this.length; ++j < m;) {
 
4926     for (var group = this[j], i = -1, n = group.length; ++i < n;) {
 
4927       if (node = group[i]) {
 
4928         transition = node[ns][id];
 
4929         subnodes = selector.call(node, node.__data__, i, j);
 
4930         subgroups.push(subgroup = []);
 
4931         for (var k = -1, o = subnodes.length; ++k < o;) {
 
4932           if (subnode = subnodes[k]) d3_transitionNode(subnode, k, ns, id, transition);
 
4933           subgroup.push(subnode);
 
4939   return d3_transition(subgroups, ns, id);
 
4942 d3_transitionPrototype.filter = function(filter) {
 
4948   if (typeof filter !== "function") filter = d3_selection_filter(filter);
 
4950   for (var j = 0, m = this.length; j < m; j++) {
 
4951     subgroups.push(subgroup = []);
 
4952     for (var group = this[j], i = 0, n = group.length; i < n; i++) {
 
4953       if ((node = group[i]) && filter.call(node, node.__data__, i, j)) {
 
4954         subgroup.push(node);
 
4959   return d3_transition(subgroups, this.namespace, this.id);
 
4961 d3.color = d3_color;
 
4963 function d3_color() {}
 
4965 d3_color.prototype.toString = function() {
 
4966   return this.rgb() + "";
 
4971 function d3_hsl(h, s, l) {
 
4972   return this instanceof d3_hsl ? void (this.h = +h, this.s = +s, this.l = +l)
 
4973       : arguments.length < 2 ? (h instanceof d3_hsl ? new d3_hsl(h.h, h.s, h.l)
 
4974       : d3_rgb_parse("" + h, d3_rgb_hsl, d3_hsl))
 
4975       : new d3_hsl(h, s, l);
 
4978 var d3_hslPrototype = d3_hsl.prototype = new d3_color;
 
4980 d3_hslPrototype.brighter = function(k) {
 
4981   k = Math.pow(0.7, arguments.length ? k : 1);
 
4982   return new d3_hsl(this.h, this.s, this.l / k);
 
4985 d3_hslPrototype.darker = function(k) {
 
4986   k = Math.pow(0.7, arguments.length ? k : 1);
 
4987   return new d3_hsl(this.h, this.s, k * this.l);
 
4990 d3_hslPrototype.rgb = function() {
 
4991   return d3_hsl_rgb(this.h, this.s, this.l);
 
4994 function d3_hsl_rgb(h, s, l) {
 
4998   /* Some simple corrections for h, s and l. */
 
4999   h = isNaN(h) ? 0 : (h %= 360) < 0 ? h + 360 : h;
 
5000   s = isNaN(s) ? 0 : s < 0 ? 0 : s > 1 ? 1 : s;
 
5001   l = l < 0 ? 0 : l > 1 ? 1 : l;
 
5003   /* From FvD 13.37, CSS Color Module Level 3 */
 
5004   m2 = l <= .5 ? l * (1 + s) : l + s - l * s;
 
5008     if (h > 360) h -= 360;
 
5009     else if (h < 0) h += 360;
 
5010     if (h < 60) return m1 + (m2 - m1) * h / 60;
 
5011     if (h < 180) return m2;
 
5012     if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;
 
5017     return Math.round(v(h) * 255);
 
5020   return new d3_rgb(vv(h + 120), vv(h), vv(h - 120));
 
5025 function d3_hcl(h, c, l) {
 
5026   return this instanceof d3_hcl ? void (this.h = +h, this.c = +c, this.l = +l)
 
5027       : arguments.length < 2 ? (h instanceof d3_hcl ? new d3_hcl(h.h, h.c, h.l)
 
5028       : (h instanceof d3_lab ? d3_lab_hcl(h.l, h.a, h.b)
 
5029       : d3_lab_hcl((h = d3_rgb_lab((h = d3.rgb(h)).r, h.g, h.b)).l, h.a, h.b)))
 
5030       : new d3_hcl(h, c, l);
 
5033 var d3_hclPrototype = d3_hcl.prototype = new d3_color;
 
5035 d3_hclPrototype.brighter = function(k) {
 
5036   return new d3_hcl(this.h, this.c, Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)));
 
5039 d3_hclPrototype.darker = function(k) {
 
5040   return new d3_hcl(this.h, this.c, Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)));
 
5043 d3_hclPrototype.rgb = function() {
 
5044   return d3_hcl_lab(this.h, this.c, this.l).rgb();
 
5047 function d3_hcl_lab(h, c, l) {
 
5048   if (isNaN(h)) h = 0;
 
5049   if (isNaN(c)) c = 0;
 
5050   return new d3_lab(l, Math.cos(h *= d3_radians) * c, Math.sin(h) * c);
 
5055 function d3_lab(l, a, b) {
 
5056   return this instanceof d3_lab ? void (this.l = +l, this.a = +a, this.b = +b)
 
5057       : arguments.length < 2 ? (l instanceof d3_lab ? new d3_lab(l.l, l.a, l.b)
 
5058       : (l instanceof d3_hcl ? d3_hcl_lab(l.h, l.c, l.l)
 
5059       : d3_rgb_lab((l = d3_rgb(l)).r, l.g, l.b)))
 
5060       : new d3_lab(l, a, b);
 
5063 // Corresponds roughly to RGB brighter/darker
 
5066 // D65 standard referent
 
5067 var d3_lab_X = 0.950470,
 
5069     d3_lab_Z = 1.088830;
 
5071 var d3_labPrototype = d3_lab.prototype = new d3_color;
 
5073 d3_labPrototype.brighter = function(k) {
 
5074   return new d3_lab(Math.min(100, this.l + d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
 
5077 d3_labPrototype.darker = function(k) {
 
5078   return new d3_lab(Math.max(0, this.l - d3_lab_K * (arguments.length ? k : 1)), this.a, this.b);
 
5081 d3_labPrototype.rgb = function() {
 
5082   return d3_lab_rgb(this.l, this.a, this.b);
 
5085 function d3_lab_rgb(l, a, b) {
 
5086   var y = (l + 16) / 116,
 
5089   x = d3_lab_xyz(x) * d3_lab_X;
 
5090   y = d3_lab_xyz(y) * d3_lab_Y;
 
5091   z = d3_lab_xyz(z) * d3_lab_Z;
 
5093     d3_xyz_rgb( 3.2404542 * x - 1.5371385 * y - 0.4985314 * z),
 
5094     d3_xyz_rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z),
 
5095     d3_xyz_rgb( 0.0556434 * x - 0.2040259 * y + 1.0572252 * z)
 
5099 function d3_lab_hcl(l, a, b) {
 
5101       ? new d3_hcl(Math.atan2(b, a) * d3_degrees, Math.sqrt(a * a + b * b), l)
 
5102       : new d3_hcl(NaN, NaN, l);
 
5105 function d3_lab_xyz(x) {
 
5106   return x > 0.206893034 ? x * x * x : (x - 4 / 29) / 7.787037;
 
5108 function d3_xyz_lab(x) {
 
5109   return x > 0.008856 ? Math.pow(x, 1 / 3) : 7.787037 * x + 4 / 29;
 
5112 function d3_xyz_rgb(r) {
 
5113   return Math.round(255 * (r <= 0.00304 ? 12.92 * r : 1.055 * Math.pow(r, 1 / 2.4) - 0.055));
 
5118 function d3_rgb(r, g, b) {
 
5119   return this instanceof d3_rgb ? void (this.r = ~~r, this.g = ~~g, this.b = ~~b)
 
5120       : arguments.length < 2 ? (r instanceof d3_rgb ? new d3_rgb(r.r, r.g, r.b)
 
5121       : d3_rgb_parse("" + r, d3_rgb, d3_hsl_rgb))
 
5122       : new d3_rgb(r, g, b);
 
5125 function d3_rgbNumber(value) {
 
5126   return new d3_rgb(value >> 16, value >> 8 & 0xff, value & 0xff);
 
5129 function d3_rgbString(value) {
 
5130   return d3_rgbNumber(value) + "";
 
5133 var d3_rgbPrototype = d3_rgb.prototype = new d3_color;
 
5135 d3_rgbPrototype.brighter = function(k) {
 
5136   k = Math.pow(0.7, arguments.length ? k : 1);
 
5141   if (!r && !g && !b) return new d3_rgb(i, i, i);
 
5142   if (r && r < i) r = i;
 
5143   if (g && g < i) g = i;
 
5144   if (b && b < i) b = i;
 
5145   return new d3_rgb(Math.min(255, r / k), Math.min(255, g / k), Math.min(255, b / k));
 
5148 d3_rgbPrototype.darker = function(k) {
 
5149   k = Math.pow(0.7, arguments.length ? k : 1);
 
5150   return new d3_rgb(k * this.r, k * this.g, k * this.b);
 
5153 d3_rgbPrototype.hsl = function() {
 
5154   return d3_rgb_hsl(this.r, this.g, this.b);
 
5157 d3_rgbPrototype.toString = function() {
 
5158   return "#" + d3_rgb_hex(this.r) + d3_rgb_hex(this.g) + d3_rgb_hex(this.b);
 
5161 function d3_rgb_hex(v) {
 
5163       ? "0" + Math.max(0, v).toString(16)
 
5164       : Math.min(255, v).toString(16);
 
5167 function d3_rgb_parse(format, rgb, hsl) {
 
5168   var r = 0, // red channel; int in [0, 255]
 
5169       g = 0, // green channel; int in [0, 255]
 
5170       b = 0, // blue channel; int in [0, 255]
 
5171       m1, // CSS color specification match
 
5172       m2, // CSS color specification type (e.g., rgb)
 
5175   /* Handle hsl, rgb. */
 
5176   m1 = /([a-z]+)\((.*)\)/i.exec(format);
 
5178     m2 = m1[2].split(",");
 
5182           parseFloat(m2[0]), // degrees
 
5183           parseFloat(m2[1]) / 100, // percentage
 
5184           parseFloat(m2[2]) / 100 // percentage
 
5189           d3_rgb_parseNumber(m2[0]),
 
5190           d3_rgb_parseNumber(m2[1]),
 
5191           d3_rgb_parseNumber(m2[2])
 
5198   if (color = d3_rgb_names.get(format.toLowerCase())) {
 
5199     return rgb(color.r, color.g, color.b);
 
5202   /* Hexadecimal colors: #rgb and #rrggbb. */
 
5203   if (format != null && format.charAt(0) === "#" && !isNaN(color = parseInt(format.slice(1), 16))) {
 
5204     if (format.length === 4) {
 
5205       r = (color & 0xf00) >> 4; r = (r >> 4) | r;
 
5206       g = (color & 0xf0); g = (g >> 4) | g;
 
5207       b = (color & 0xf); b = (b << 4) | b;
 
5208     } else if (format.length === 7) {
 
5209       r = (color & 0xff0000) >> 16;
 
5210       g = (color & 0xff00) >> 8;
 
5215   return rgb(r, g, b);
 
5218 function d3_rgb_hsl(r, g, b) {
 
5219   var min = Math.min(r /= 255, g /= 255, b /= 255),
 
5220       max = Math.max(r, g, b),
 
5224       l = (max + min) / 2;
 
5226     s = l < .5 ? d / (max + min) : d / (2 - max - min);
 
5227     if (r == max) h = (g - b) / d + (g < b ? 6 : 0);
 
5228     else if (g == max) h = (b - r) / d + 2;
 
5229     else h = (r - g) / d + 4;
 
5233     s = l > 0 && l < 1 ? 0 : h;
 
5235   return new d3_hsl(h, s, l);
 
5238 function d3_rgb_lab(r, g, b) {
 
5242   var x = d3_xyz_lab((0.4124564 * r + 0.3575761 * g + 0.1804375 * b) / d3_lab_X),
 
5243       y = d3_xyz_lab((0.2126729 * r + 0.7151522 * g + 0.0721750 * b) / d3_lab_Y),
 
5244       z = d3_xyz_lab((0.0193339 * r + 0.1191920 * g + 0.9503041 * b) / d3_lab_Z);
 
5245   return d3_lab(116 * y - 16, 500 * (x - y), 200 * (y - z));
 
5248 function d3_rgb_xyz(r) {
 
5249   return (r /= 255) <= 0.04045 ? r / 12.92 : Math.pow((r + 0.055) / 1.055, 2.4);
 
5252 function d3_rgb_parseNumber(c) { // either integer or percentage
 
5253   var f = parseFloat(c);
 
5254   return c.charAt(c.length - 1) === "%" ? Math.round(f * 2.55) : f;
 
5257 var d3_rgb_names = d3.map({
 
5258   aliceblue: 0xf0f8ff,
 
5259   antiquewhite: 0xfaebd7,
 
5261   aquamarine: 0x7fffd4,
 
5266   blanchedalmond: 0xffebcd,
 
5268   blueviolet: 0x8a2be2,
 
5270   burlywood: 0xdeb887,
 
5271   cadetblue: 0x5f9ea0,
 
5272   chartreuse: 0x7fff00,
 
5273   chocolate: 0xd2691e,
 
5275   cornflowerblue: 0x6495ed,
 
5281   darkgoldenrod: 0xb8860b,
 
5283   darkgreen: 0x006400,
 
5285   darkkhaki: 0xbdb76b,
 
5286   darkmagenta: 0x8b008b,
 
5287   darkolivegreen: 0x556b2f,
 
5288   darkorange: 0xff8c00,
 
5289   darkorchid: 0x9932cc,
 
5291   darksalmon: 0xe9967a,
 
5292   darkseagreen: 0x8fbc8f,
 
5293   darkslateblue: 0x483d8b,
 
5294   darkslategray: 0x2f4f4f,
 
5295   darkslategrey: 0x2f4f4f,
 
5296   darkturquoise: 0x00ced1,
 
5297   darkviolet: 0x9400d3,
 
5299   deepskyblue: 0x00bfff,
 
5302   dodgerblue: 0x1e90ff,
 
5303   firebrick: 0xb22222,
 
5304   floralwhite: 0xfffaf0,
 
5305   forestgreen: 0x228b22,
 
5307   gainsboro: 0xdcdcdc,
 
5308   ghostwhite: 0xf8f8ff,
 
5310   goldenrod: 0xdaa520,
 
5313   greenyellow: 0xadff2f,
 
5317   indianred: 0xcd5c5c,
 
5322   lavenderblush: 0xfff0f5,
 
5323   lawngreen: 0x7cfc00,
 
5324   lemonchiffon: 0xfffacd,
 
5325   lightblue: 0xadd8e6,
 
5326   lightcoral: 0xf08080,
 
5327   lightcyan: 0xe0ffff,
 
5328   lightgoldenrodyellow: 0xfafad2,
 
5329   lightgray: 0xd3d3d3,
 
5330   lightgreen: 0x90ee90,
 
5331   lightgrey: 0xd3d3d3,
 
5332   lightpink: 0xffb6c1,
 
5333   lightsalmon: 0xffa07a,
 
5334   lightseagreen: 0x20b2aa,
 
5335   lightskyblue: 0x87cefa,
 
5336   lightslategray: 0x778899,
 
5337   lightslategrey: 0x778899,
 
5338   lightsteelblue: 0xb0c4de,
 
5339   lightyellow: 0xffffe0,
 
5341   limegreen: 0x32cd32,
 
5345   mediumaquamarine: 0x66cdaa,
 
5346   mediumblue: 0x0000cd,
 
5347   mediumorchid: 0xba55d3,
 
5348   mediumpurple: 0x9370db,
 
5349   mediumseagreen: 0x3cb371,
 
5350   mediumslateblue: 0x7b68ee,
 
5351   mediumspringgreen: 0x00fa9a,
 
5352   mediumturquoise: 0x48d1cc,
 
5353   mediumvioletred: 0xc71585,
 
5354   midnightblue: 0x191970,
 
5355   mintcream: 0xf5fffa,
 
5356   mistyrose: 0xffe4e1,
 
5358   navajowhite: 0xffdead,
 
5362   olivedrab: 0x6b8e23,
 
5364   orangered: 0xff4500,
 
5366   palegoldenrod: 0xeee8aa,
 
5367   palegreen: 0x98fb98,
 
5368   paleturquoise: 0xafeeee,
 
5369   palevioletred: 0xdb7093,
 
5370   papayawhip: 0xffefd5,
 
5371   peachpuff: 0xffdab9,
 
5375   powderblue: 0xb0e0e6,
 
5377   rebeccapurple: 0x663399,
 
5379   rosybrown: 0xbc8f8f,
 
5380   royalblue: 0x4169e1,
 
5381   saddlebrown: 0x8b4513,
 
5383   sandybrown: 0xf4a460,
 
5389   slateblue: 0x6a5acd,
 
5390   slategray: 0x708090,
 
5391   slategrey: 0x708090,
 
5393   springgreen: 0x00ff7f,
 
5394   steelblue: 0x4682b4,
 
5399   turquoise: 0x40e0d0,
 
5403   whitesmoke: 0xf5f5f5,
 
5405   yellowgreen: 0x9acd32
 
5408 d3_rgb_names.forEach(function(key, value) {
 
5409   d3_rgb_names.set(key, d3_rgbNumber(value));
 
5412 d3.interpolateRgb = d3_interpolateRgb;
 
5414 function d3_interpolateRgb(a, b) {
 
5423   return function(t) {
 
5425         + d3_rgb_hex(Math.round(ar + br * t))
 
5426         + d3_rgb_hex(Math.round(ag + bg * t))
 
5427         + d3_rgb_hex(Math.round(ab + bb * t));
 
5431 d3.interpolateObject = d3_interpolateObject;
 
5433 function d3_interpolateObject(a, b) {
 
5439       i[k] = d3_interpolate(a[k], b[k]);
 
5449   return function(t) {
 
5450     for (k in i) c[k] = i[k](t);
 
5455 d3.interpolateArray = d3_interpolateArray;
 
5457 function d3_interpolateArray(a, b) {
 
5462       n0 = Math.min(a.length, b.length),
 
5464   for (i = 0; i < n0; ++i) x.push(d3_interpolate(a[i], b[i]));
 
5465   for (; i < na; ++i) c[i] = a[i];
 
5466   for (; i < nb; ++i) c[i] = b[i];
 
5467   return function(t) {
 
5468     for (i = 0; i < n0; ++i) c[i] = x[i](t);
 
5472 d3.interpolateNumber = d3_interpolateNumber;
 
5474 function d3_interpolateNumber(a, b) {
 
5476   return function(t) { return a * (1 - t) + b * t; };
 
5479 d3.interpolateString = d3_interpolateString;
 
5481 function d3_interpolateString(a, b) {
 
5482   var bi = d3_interpolate_numberA.lastIndex = d3_interpolate_numberB.lastIndex = 0, // scan index for next number in b
 
5483       am, // current match in a
 
5484       bm, // current match in b
 
5485       bs, // string preceding current number in b, if any
 
5486       i = -1, // index in s
 
5487       s = [], // string constants and placeholders
 
5488       q = []; // number interpolators
 
5490   // Coerce inputs to strings.
 
5491   a = a + "", b = b + "";
 
5493   // Interpolate pairs of numbers in a & b.
 
5494   while ((am = d3_interpolate_numberA.exec(a))
 
5495       && (bm = d3_interpolate_numberB.exec(b))) {
 
5496     if ((bs = bm.index) > bi) { // a string precedes the next number in b
 
5497       bs = b.slice(bi, bs);
 
5498       if (s[i]) s[i] += bs; // coalesce with previous string
 
5501     if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match
 
5502       if (s[i]) s[i] += bm; // coalesce with previous string
 
5504     } else { // interpolate non-matching numbers
 
5506       q.push({i: i, x: d3_interpolateNumber(am, bm)});
 
5508     bi = d3_interpolate_numberB.lastIndex;
 
5511   // Add remains of b.
 
5512   if (bi < b.length) {
 
5514     if (s[i]) s[i] += bs; // coalesce with previous string
 
5518   // Special optimization for only a single match.
 
5519   // Otherwise, interpolate each of the numbers and rejoin the string.
 
5521       ? (q[0] ? (b = q[0].x, function(t) { return b(t) + ""; })
 
5522       : function() { return b; })
 
5523       : (b = q.length, function(t) {
 
5524           for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);
 
5529 var d3_interpolate_numberA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,
 
5530     d3_interpolate_numberB = new RegExp(d3_interpolate_numberA.source, "g");
 
5532 d3.interpolate = d3_interpolate;
 
5534 function d3_interpolate(a, b) {
 
5535   var i = d3.interpolators.length, f;
 
5536   while (--i >= 0 && !(f = d3.interpolators[i](a, b)));
 
5540 d3.interpolators = [
 
5543     return (t === "string" ? (d3_rgb_names.has(b) || /^(#|rgb\(|hsl\()/.test(b) ? d3_interpolateRgb : d3_interpolateString)
 
5544         : b instanceof d3_color ? d3_interpolateRgb
 
5545         : Array.isArray(b) ? d3_interpolateArray
 
5546         : t === "object" && isNaN(b) ? d3_interpolateObject
 
5547         : d3_interpolateNumber)(a, b);
 
5551 d3.transform = function(string) {
 
5552   var g = d3_document.createElementNS(d3.ns.prefix.svg, "g");
 
5553   return (d3.transform = function(string) {
 
5554     if (string != null) {
 
5555       g.setAttribute("transform", string);
 
5556       var t = g.transform.baseVal.consolidate();
 
5558     return new d3_transform(t ? t.matrix : d3_transformIdentity);
 
5562 // Compute x-scale and normalize the first row.
 
5563 // Compute shear and make second row orthogonal to first.
 
5564 // Compute y-scale and normalize the second row.
 
5565 // Finally, compute the rotation.
 
5566 function d3_transform(m) {
 
5567   var r0 = [m.a, m.b],
 
5569       kx = d3_transformNormalize(r0),
 
5570       kz = d3_transformDot(r0, r1),
 
5571       ky = d3_transformNormalize(d3_transformCombine(r1, r0, -kz)) || 0;
 
5572   if (r0[0] * r1[1] < r1[0] * r0[1]) {
 
5578   this.rotate = (kx ? Math.atan2(r0[1], r0[0]) : Math.atan2(-r1[0], r1[1])) * d3_degrees;
 
5579   this.translate = [m.e, m.f];
 
5580   this.scale = [kx, ky];
 
5581   this.skew = ky ? Math.atan2(kz, ky) * d3_degrees : 0;
 
5584 d3_transform.prototype.toString = function() {
 
5585   return "translate(" + this.translate
 
5586       + ")rotate(" + this.rotate
 
5587       + ")skewX(" + this.skew
 
5588       + ")scale(" + this.scale
 
5592 function d3_transformDot(a, b) {
 
5593   return a[0] * b[0] + a[1] * b[1];
 
5596 function d3_transformNormalize(a) {
 
5597   var k = Math.sqrt(d3_transformDot(a, a));
 
5605 function d3_transformCombine(a, b, k) {
 
5611 var d3_transformIdentity = {a: 1, b: 0, c: 0, d: 1, e: 0, f: 0};
 
5613 d3.interpolateTransform = d3_interpolateTransform;
 
5615 function d3_interpolateTransform(a, b) {
 
5616   var s = [], // string constants and placeholders
 
5617       q = [], // number interpolators
 
5619       A = d3.transform(a),
 
5620       B = d3.transform(b),
 
5630   if (ta[0] != tb[0] || ta[1] != tb[1]) {
 
5631     s.push("translate(", null, ",", null, ")");
 
5632     q.push({i: 1, x: d3_interpolateNumber(ta[0], tb[0])}, {i: 3, x: d3_interpolateNumber(ta[1], tb[1])});
 
5633   } else if (tb[0] || tb[1]) {
 
5634     s.push("translate(" + tb + ")");
 
5640     if (ra - rb > 180) rb += 360; else if (rb - ra > 180) ra += 360; // shortest path
 
5641     q.push({i: s.push(s.pop() + "rotate(", null, ")") - 2, x: d3_interpolateNumber(ra, rb)});
 
5643     s.push(s.pop() + "rotate(" + rb + ")");
 
5647     q.push({i: s.push(s.pop() + "skewX(", null, ")") - 2, x: d3_interpolateNumber(wa, wb)});
 
5649     s.push(s.pop() + "skewX(" + wb + ")");
 
5652   if (ka[0] != kb[0] || ka[1] != kb[1]) {
 
5653     n = s.push(s.pop() + "scale(", null, ",", null, ")");
 
5654     q.push({i: n - 4, x: d3_interpolateNumber(ka[0], kb[0])}, {i: n - 2, x: d3_interpolateNumber(ka[1], kb[1])});
 
5655   } else if (kb[0] != 1 || kb[1] != 1) {
 
5656     s.push(s.pop() + "scale(" + kb + ")");
 
5660   return function(t) {
 
5662     while (++i < n) s[(o = q[i]).i] = o.x(t);
 
5667 d3_transitionPrototype.tween = function(name, tween) {
 
5668   var id = this.id, ns = this.namespace;
 
5669   if (arguments.length < 2) return this.node()[ns][id].tween.get(name);
 
5670   return d3_selection_each(this, tween == null
 
5671         ? function(node) { node[ns][id].tween.remove(name); }
 
5672         : function(node) { node[ns][id].tween.set(name, tween); });
 
5675 function d3_transition_tween(groups, name, value, tween) {
 
5676   var id = groups.id, ns = groups.namespace;
 
5677   return d3_selection_each(groups, typeof value === "function"
 
5678       ? function(node, i, j) { node[ns][id].tween.set(name, tween(value.call(node, node.__data__, i, j))); }
 
5679       : (value = tween(value), function(node) { node[ns][id].tween.set(name, value); }));
 
5682 d3_transitionPrototype.attr = function(nameNS, value) {
 
5683   if (arguments.length < 2) {
 
5685     // For attr(object), the object specifies the names and values of the
 
5686     // attributes to transition. The values may be functions that are
 
5687     // evaluated for each element.
 
5688     for (value in nameNS) this.attr(value, nameNS[value]);
 
5692   var interpolate = nameNS == "transform" ? d3_interpolateTransform : d3_interpolate,
 
5693       name = d3.ns.qualify(nameNS);
 
5695   // For attr(string, null), remove the attribute with the specified name.
 
5696   function attrNull() {
 
5697     this.removeAttribute(name);
 
5699   function attrNullNS() {
 
5700     this.removeAttributeNS(name.space, name.local);
 
5703   // For attr(string, string), set the attribute with the specified name.
 
5704   function attrTween(b) {
 
5705     return b == null ? attrNull : (b += "", function() {
 
5706       var a = this.getAttribute(name), i;
 
5707       return a !== b && (i = interpolate(a, b), function(t) { this.setAttribute(name, i(t)); });
 
5710   function attrTweenNS(b) {
 
5711     return b == null ? attrNullNS : (b += "", function() {
 
5712       var a = this.getAttributeNS(name.space, name.local), i;
 
5713       return a !== b && (i = interpolate(a, b), function(t) { this.setAttributeNS(name.space, name.local, i(t)); });
 
5717   return d3_transition_tween(this, "attr." + nameNS, value, name.local ? attrTweenNS : attrTween);
 
5720 d3_transitionPrototype.attrTween = function(nameNS, tween) {
 
5721   var name = d3.ns.qualify(nameNS);
 
5723   function attrTween(d, i) {
 
5724     var f = tween.call(this, d, i, this.getAttribute(name));
 
5725     return f && function(t) { this.setAttribute(name, f(t)); };
 
5727   function attrTweenNS(d, i) {
 
5728     var f = tween.call(this, d, i, this.getAttributeNS(name.space, name.local));
 
5729     return f && function(t) { this.setAttributeNS(name.space, name.local, f(t)); };
 
5732   return this.tween("attr." + nameNS, name.local ? attrTweenNS : attrTween);
 
5735 d3_transitionPrototype.style = function(name, value, priority) {
 
5736   var n = arguments.length;
 
5739     // For style(object) or style(object, string), the object specifies the
 
5740     // names and values of the attributes to set or remove. The values may be
 
5741     // functions that are evaluated for each element. The optional string
 
5742     // specifies the priority.
 
5743     if (typeof name !== "string") {
 
5744       if (n < 2) value = "";
 
5745       for (priority in name) this.style(priority, name[priority], value);
 
5749     // For style(string, string) or style(string, function), use the default
 
5750     // priority. The priority is ignored for style(string, null).
 
5754   // For style(name, null) or style(name, null, priority), remove the style
 
5755   // property with the specified name. The priority is ignored.
 
5756   function styleNull() {
 
5757     this.style.removeProperty(name);
 
5760   // For style(name, string) or style(name, string, priority), set the style
 
5761   // property with the specified name, using the specified priority.
 
5762   // Otherwise, a name, value and priority are specified, and handled as below.
 
5763   function styleString(b) {
 
5764     return b == null ? styleNull : (b += "", function() {
 
5765       var a = d3_window(this).getComputedStyle(this, null).getPropertyValue(name), i;
 
5766       return a !== b && (i = d3_interpolate(a, b), function(t) { this.style.setProperty(name, i(t), priority); });
 
5770   return d3_transition_tween(this, "style." + name, value, styleString);
 
5773 d3_transitionPrototype.styleTween = function(name, tween, priority) {
 
5774   if (arguments.length < 3) priority = "";
 
5776   function styleTween(d, i) {
 
5777     var f = tween.call(this, d, i, d3_window(this).getComputedStyle(this, null).getPropertyValue(name));
 
5778     return f && function(t) { this.style.setProperty(name, f(t), priority); };
 
5781   return this.tween("style." + name, styleTween);
 
5784 d3_transitionPrototype.text = function(value) {
 
5785   return d3_transition_tween(this, "text", value, d3_transition_text);
 
5788 function d3_transition_text(b) {
 
5789   if (b == null) b = "";
 
5790   return function() { this.textContent = b; };
 
5793 d3_transitionPrototype.remove = function() {
 
5794   var ns = this.namespace;
 
5795   return this.each("end.transition", function() {
 
5797     if (this[ns].count < 2 && (p = this.parentNode)) p.removeChild(this);
 
5801 var d3_ease_default = function() { return d3_identity; };
 
5803 var d3_ease = d3.map({
 
5804   linear: d3_ease_default,
 
5806   quad: function() { return d3_ease_quad; },
 
5807   cubic: function() { return d3_ease_cubic; },
 
5808   sin: function() { return d3_ease_sin; },
 
5809   exp: function() { return d3_ease_exp; },
 
5810   circle: function() { return d3_ease_circle; },
 
5811   elastic: d3_ease_elastic,
 
5813   bounce: function() { return d3_ease_bounce; }
 
5816 var d3_ease_mode = d3.map({
 
5818   "out": d3_ease_reverse,
 
5819   "in-out": d3_ease_reflect,
 
5820   "out-in": function(f) { return d3_ease_reflect(d3_ease_reverse(f)); }
 
5823 d3.ease = function(name) {
 
5824   var i = name.indexOf("-"),
 
5825       t = i >= 0 ? name.slice(0, i) : name,
 
5826       m = i >= 0 ? name.slice(i + 1) : "in";
 
5827   t = d3_ease.get(t) || d3_ease_default;
 
5828   m = d3_ease_mode.get(m) || d3_identity;
 
5829   return d3_ease_clamp(m(t.apply(null, d3_arraySlice.call(arguments, 1))));
 
5832 function d3_ease_clamp(f) {
 
5833   return function(t) {
 
5834     return t <= 0 ? 0 : t >= 1 ? 1 : f(t);
 
5838 function d3_ease_reverse(f) {
 
5839   return function(t) {
 
5840     return 1 - f(1 - t);
 
5844 function d3_ease_reflect(f) {
 
5845   return function(t) {
 
5846     return .5 * (t < .5 ? f(2 * t) : (2 - f(2 - 2 * t)));
 
5850 function d3_ease_quad(t) {
 
5854 function d3_ease_cubic(t) {
 
5858 // Optimized clamp(reflect(poly(3))).
 
5859 function d3_ease_cubicInOut(t) {
 
5860   if (t <= 0) return 0;
 
5861   if (t >= 1) return 1;
 
5862   var t2 = t * t, t3 = t2 * t;
 
5863   return 4 * (t < .5 ? t3 : 3 * (t - t2) + t3 - .75);
 
5866 function d3_ease_poly(e) {
 
5867   return function(t) {
 
5868     return Math.pow(t, e);
 
5872 function d3_ease_sin(t) {
 
5873   return 1 - Math.cos(t * halfπ);
 
5876 function d3_ease_exp(t) {
 
5877   return Math.pow(2, 10 * (t - 1));
 
5880 function d3_ease_circle(t) {
 
5881   return 1 - Math.sqrt(1 - t * t);
 
5884 function d3_ease_elastic(a, p) {
 
5886   if (arguments.length < 2) p = 0.45;
 
5887   if (arguments.length) s = p / τ * Math.asin(1 / a);
 
5888   else a = 1, s = p / 4;
 
5889   return function(t) {
 
5890     return 1 + a * Math.pow(2, -10 * t) * Math.sin((t - s) * τ / p);
 
5894 function d3_ease_back(s) {
 
5895   if (!s) s = 1.70158;
 
5896   return function(t) {
 
5897     return t * t * ((s + 1) * t - s);
 
5901 function d3_ease_bounce(t) {
 
5902   return t < 1 / 2.75 ? 7.5625 * t * t
 
5903       : t < 2 / 2.75 ? 7.5625 * (t -= 1.5 / 2.75) * t + .75
 
5904       : t < 2.5 / 2.75 ? 7.5625 * (t -= 2.25 / 2.75) * t + .9375
 
5905       : 7.5625 * (t -= 2.625 / 2.75) * t + .984375;
 
5908 d3_transitionPrototype.ease = function(value) {
 
5909   var id = this.id, ns = this.namespace;
 
5910   if (arguments.length < 1) return this.node()[ns][id].ease;
 
5911   if (typeof value !== "function") value = d3.ease.apply(d3, arguments);
 
5912   return d3_selection_each(this, function(node) { node[ns][id].ease = value; });
 
5915 d3_transitionPrototype.delay = function(value) {
 
5916   var id = this.id, ns = this.namespace;
 
5917   if (arguments.length < 1) return this.node()[ns][id].delay;
 
5918   return d3_selection_each(this, typeof value === "function"
 
5919       ? function(node, i, j) { node[ns][id].delay = +value.call(node, node.__data__, i, j); }
 
5920       : (value = +value, function(node) { node[ns][id].delay = value; }));
 
5923 d3_transitionPrototype.duration = function(value) {
 
5924   var id = this.id, ns = this.namespace;
 
5925   if (arguments.length < 1) return this.node()[ns][id].duration;
 
5926   return d3_selection_each(this, typeof value === "function"
 
5927       ? function(node, i, j) { node[ns][id].duration = Math.max(1, value.call(node, node.__data__, i, j)); }
 
5928       : (value = Math.max(1, value), function(node) { node[ns][id].duration = value; }));
 
5931 d3_transitionPrototype.each = function(type, listener) {
 
5932   var id = this.id, ns = this.namespace;
 
5933   if (arguments.length < 2) {
 
5934     var inherit = d3_transitionInherit,
 
5935         inheritId = d3_transitionInheritId;
 
5937       d3_transitionInheritId = id;
 
5938       d3_selection_each(this, function(node, i, j) {
 
5939         d3_transitionInherit = node[ns][id];
 
5940         type.call(node, node.__data__, i, j);
 
5943       d3_transitionInherit = inherit;
 
5944       d3_transitionInheritId = inheritId;
 
5947     d3_selection_each(this, function(node) {
 
5948       var transition = node[ns][id];
 
5949       (transition.event || (transition.event = d3.dispatch("start", "end", "interrupt"))).on(type, listener);
 
5955 d3_transitionPrototype.transition = function() {
 
5957       id1 = ++d3_transitionId,
 
5958       ns = this.namespace,
 
5965   for (var j = 0, m = this.length; j < m; j++) {
 
5966     subgroups.push(subgroup = []);
 
5967     for (var group = this[j], i = 0, n = group.length; i < n; i++) {
 
5968       if (node = group[i]) {
 
5969         transition = node[ns][id0];
 
5970         d3_transitionNode(node, i, ns, id1, {time: transition.time, ease: transition.ease, delay: transition.delay + transition.duration, duration: transition.duration});
 
5972       subgroup.push(node);
 
5976   return d3_transition(subgroups, ns, id1);
 
5979 function d3_transitionNamespace(name) {
 
5980   return name == null ? "__transition__" : "__transition_" + name + "__";
 
5983 function d3_transitionNode(node, i, ns, id, inherit) {
 
5984   var lock = node[ns] || (node[ns] = {active: 0, count: 0}),
 
5985       transition = lock[id];
 
5988     var time = inherit.time;
 
5990     transition = lock[id] = {
 
5993       delay: inherit.delay,
 
5994       duration: inherit.duration,
 
5999     inherit = null; // allow gc
 
6003     d3.timer(function(elapsed) {
 
6004       var delay = transition.delay,
 
6007           timer = d3_timer_active,
 
6010       timer.t = delay + time;
 
6011       if (delay <= elapsed) return start(elapsed - delay);
 
6014       function start(elapsed) {
 
6015         if (lock.active > id) return stop();
 
6017         var active = lock[lock.active];
 
6020           delete lock[lock.active];
 
6021           active.event && active.event.interrupt.call(node, node.__data__, active.index);
 
6026         transition.event && transition.event.start.call(node, node.__data__, i);
 
6028         transition.tween.forEach(function(key, value) {
 
6029           if (value = value.call(node, node.__data__, i)) {
 
6030             tweened.push(value);
 
6034         // Deferred capture to allow tweens to initialize ease & duration.
 
6035         ease = transition.ease;
 
6036         duration = transition.duration;
 
6038         d3.timer(function() { // defer to end of current frame
 
6039           timer.c = tick(elapsed || 1) ? d3_true : tick;
 
6044       function tick(elapsed) {
 
6045         if (lock.active !== id) return 1;
 
6047         var t = elapsed / duration,
 
6052           tweened[--n].call(node, e);
 
6056           transition.event && transition.event.end.call(node, node.__data__, i);
 
6062         if (--lock.count) delete lock[id];
 
6063         else delete node[ns];
 
6070 d3.xhr = d3_xhrType(d3_identity);
 
6072 function d3_xhrType(response) {
 
6073   return function(url, mimeType, callback) {
 
6074     if (arguments.length === 2 && typeof mimeType === "function") callback = mimeType, mimeType = null;
 
6075     return d3_xhr(url, mimeType, response, callback);
 
6079 function d3_xhr(url, mimeType, response, callback) {
 
6081       dispatch = d3.dispatch("beforesend", "progress", "load", "error"),
 
6083       request = new XMLHttpRequest,
 
6084       responseType = null;
 
6086   // If IE does not support CORS, use XDomainRequest.
 
6087   if (this.XDomainRequest
 
6088       && !("withCredentials" in request)
 
6089       && /^(http(s)?:)?\/\//.test(url)) request = new XDomainRequest;
 
6092       ? request.onload = request.onerror = respond
 
6093       : request.onreadystatechange = function() { request.readyState > 3 && respond(); };
 
6095   function respond() {
 
6096     var status = request.status, result;
 
6097     if (!status && d3_xhrHasResponse(request) || status >= 200 && status < 300 || status === 304) {
 
6099         result = response.call(xhr, request);
 
6101         dispatch.error.call(xhr, e);
 
6104       dispatch.load.call(xhr, result);
 
6106       dispatch.error.call(xhr, request);
 
6110   request.onprogress = function(event) {
 
6113     try { dispatch.progress.call(xhr, request); }
 
6114     finally { d3.event = o; }
 
6117   xhr.header = function(name, value) {
 
6118     name = (name + "").toLowerCase();
 
6119     if (arguments.length < 2) return headers[name];
 
6120     if (value == null) delete headers[name];
 
6121     else headers[name] = value + "";
 
6125   // If mimeType is non-null and no Accept header is set, a default is used.
 
6126   xhr.mimeType = function(value) {
 
6127     if (!arguments.length) return mimeType;
 
6128     mimeType = value == null ? null : value + "";
 
6132   // Specifies what type the response value should take;
 
6133   // for instance, arraybuffer, blob, document, or text.
 
6134   xhr.responseType = function(value) {
 
6135     if (!arguments.length) return responseType;
 
6136     responseType = value;
 
6140   // Specify how to convert the response content to a specific type;
 
6141   // changes the callback value on "load" events.
 
6142   xhr.response = function(value) {
 
6147   // Convenience methods.
 
6148   ["get", "post"].forEach(function(method) {
 
6149     xhr[method] = function() {
 
6150       return xhr.send.apply(xhr, [method].concat(d3_array(arguments)));
 
6154   // If callback is non-null, it will be used for error and load events.
 
6155   xhr.send = function(method, data, callback) {
 
6156     if (arguments.length === 2 && typeof data === "function") callback = data, data = null;
 
6157     request.open(method, url, true);
 
6158     if (mimeType != null && !("accept" in headers)) headers["accept"] = mimeType + ",*/*";
 
6159     if (request.setRequestHeader) for (var name in headers) request.setRequestHeader(name, headers[name]);
 
6160     if (mimeType != null && request.overrideMimeType) request.overrideMimeType(mimeType);
 
6161     if (responseType != null) request.responseType = responseType;
 
6162     if (callback != null) xhr.on("error", callback).on("load", function(request) { callback(null, request); });
 
6163     dispatch.beforesend.call(xhr, request);
 
6164     request.send(data == null ? null : data);
 
6168   xhr.abort = function() {
 
6173   d3.rebind(xhr, dispatch, "on");
 
6175   return callback == null ? xhr : xhr.get(d3_xhr_fixCallback(callback));
 
6178 function d3_xhr_fixCallback(callback) {
 
6179   return callback.length === 1
 
6180       ? function(error, request) { callback(error == null ? request : null); }
 
6184 function d3_xhrHasResponse(request) {
 
6185   var type = request.responseType;
 
6186   return type && type !== "text"
 
6187       ? request.response // null on error
 
6188       : request.responseText; // "" on error
 
6191 d3.text = d3_xhrType(function(request) {
 
6192   return request.responseText;
 
6195 d3.json = function(url, callback) {
 
6196   return d3_xhr(url, "application/json", d3_json, callback);
 
6199 function d3_json(request) {
 
6200   return JSON.parse(request.responseText);
 
6203 d3.html = function(url, callback) {
 
6204   return d3_xhr(url, "text/html", d3_html, callback);
 
6207 function d3_html(request) {
 
6208   var range = d3_document.createRange();
 
6209   range.selectNode(d3_document.body);
 
6210   return range.createContextualFragment(request.responseText);
 
6213 d3.xml = d3_xhrType(function(request) {
 
6214   return request.responseXML;
 
6216   if (typeof define === "function" && define.amd) define(d3);
 
6217   else if (typeof module === "object" && module.exports) module.exports = d3;
 
6220 d3.combobox = function() {
 
6221     var event = d3.dispatch('accept'),
 
6225         caseSensitive = false;
 
6227     var fetcher = function(val, cb) {
 
6228         cb(data.filter(function(d) {
 
6232                 .indexOf(val.toLowerCase()) !== -1;
 
6236     var combobox = function(input, attachTo) {
 
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() {
 
6370                 if (input.property('selectionEnd') === input.property('value').length) {
 
6378             if (!suggestions.length) return;
 
6379             idx = Math.max(Math.min(idx + dir, suggestions.length - 1), 0);
 
6380             input.property('value', suggestions[idx].value);
 
6386             var value = input.property('value'),
 
6387                 start = input.property('selectionStart'),
 
6388                 end = input.property('selectionEnd');
 
6391                 value = value.substring(0, start);
 
6397         function fetch(v, cb) {
 
6398             fetcher.call(input, v, function(_) {
 
6404         function autocomplete() {
 
6405             var v = caseSensitive ? value() : value().toLowerCase();
 
6409             for (var i = 0; i < suggestions.length; i++) {
 
6410                 var suggestion = suggestions[i].value,
 
6411                     compare = caseSensitive ? suggestion : suggestion.toLowerCase();
 
6413                 if (compare.indexOf(v) === 0) {
 
6415                     input.property('value', suggestion);
 
6416                     input.node().setSelectionRange(v.length, suggestion.length);
 
6423             if (suggestions.length >= minItems && document.activeElement === input.node()) {
 
6430             var options = container
 
6431                 .selectAll('a.combobox-option')
 
6432                 .data(suggestions, function(d) { return d.value; });
 
6434             options.enter().append('a')
 
6435                 .attr('class', 'combobox-option')
 
6436                 .text(function(d) { return d.value; });
 
6439                 .attr('title', function(d) { return d.title; })
 
6440                 .classed('selected', function(d, i) { return i == idx; })
 
6441                 .on('mouseover', select)
 
6442                 .on('click', accept)
 
6448             var node = attachTo ? attachTo.node() : input.node(),
 
6449                 rect = node.getBoundingClientRect();
 
6452                 'left': rect.left + 'px',
 
6453                 'width': rect.width + 'px',
 
6454                 'top': rect.height + rect.top + 'px'
 
6458         function select(d, i) {
 
6463         function ensureVisible() {
 
6464             var node = container.selectAll('a.selected').node();
 
6465             if (node) node.scrollIntoView();
 
6468         function accept(d) {
 
6471                 .property('value', d.value)
 
6478     combobox.fetcher = function(_) {
 
6479         if (!arguments.length) return fetcher;
 
6484     combobox.data = function(_) {
 
6485         if (!arguments.length) return data;
 
6490     combobox.minItems = function(_) {
 
6491         if (!arguments.length) return minItems;
 
6496     combobox.caseSensitive = function(_) {
 
6497         if (!arguments.length) return caseSensitive;
 
6502     return d3.rebind(combobox, event, 'on');
 
6505 d3.combobox.off = function(input) {
 
6510         .on('focus.typeahead', null)
 
6511         .on('blur.typeahead', null)
 
6512         .on('keydown.typeahead', null)
 
6513         .on('keyup.typeahead', null)
 
6514         .on('input.typeahead', null)
 
6516             d3.select(this.parentNode).selectAll('.combobox-caret')
 
6517                 .filter(function(d) { return d === input.node(); })
 
6518                 .on('mousedown', null);
 
6521     d3.select(document.body)
 
6522         .on('scroll.combobox', null);
 
6524 d3.geo.tile = function() {
 
6525   var size = [960, 500],
 
6527       scaleExtent = [0, 20],
 
6528       translate = [size[0] / 2, size[1] / 2],
 
6532       return Math.min(scaleExtent[1], Math.max(scaleExtent[0], _));
 
6536     var z = Math.max(Math.log(scale) / Math.LN2 - 8, 0),
 
6537         z0 = bound(Math.round(z + zoomDelta)),
 
6538         k = Math.pow(2, z - z0 + 8),
 
6539         origin = [(translate[0] - scale / 2) / k, (translate[1] - scale / 2) / k],
 
6541         cols = d3.range(Math.max(0, Math.floor(-origin[0])), Math.max(0, Math.ceil(size[0] / k - origin[0]))),
 
6542         rows = d3.range(Math.max(0, Math.floor(-origin[1])), Math.max(0, Math.ceil(size[1] / k - origin[1])));
 
6544     rows.forEach(function(y) {
 
6545       cols.forEach(function(x) {
 
6546         tiles.push([x, y, z0]);
 
6550     tiles.translate = origin;
 
6556   tile.scaleExtent = function(_) {
 
6557     if (!arguments.length) return scaleExtent;
 
6562   tile.size = function(_) {
 
6563     if (!arguments.length) return size;
 
6568   tile.scale = function(_) {
 
6569     if (!arguments.length) return scale;
 
6574   tile.translate = function(_) {
 
6575     if (!arguments.length) return translate;
 
6580   tile.zoomDelta = function(_) {
 
6581     if (!arguments.length) return zoomDelta;
 
6588 d3.jsonp = function (url, callback) {
 
6590     var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
 
6592     while (++i < 15) c += chars.charAt(Math.floor(Math.random() * 52));
 
6596   function create(url) {
 
6597     var e = url.match(/callback=d3.jsonp.(\w+)/),
 
6598       c = e ? e[1] : rand();
 
6599     d3.jsonp[c] = function(data) {
 
6604     return 'd3.jsonp.' + c;
 
6607   var cb = create(url),
 
6608     script = d3.select('head')
 
6610     .attr('type', 'text/javascript')
 
6611     .attr('src', url.replace(/(\{|%7B)callback(\}|%7D)/, cb));
 
6614  * This code is licensed under the MIT license.
 
6616  * Copyright © 2013, iD authors.
 
6618  * Portions copyright © 2011, Keith Cirkel
 
6619  * See https://github.com/keithamus/jwerty
 
6622 d3.keybinding = function(namespace) {
 
6625     function matches(binding, event) {
 
6626         for (var p in binding.event) {
 
6627             if (event[p] != binding.event[p])
 
6633     function testBindings(isCapturing) {
 
6634         for (var i = 0; i < bindings.length; i++) {
 
6635             var binding = bindings[i];
 
6637             if (!!binding.capture === isCapturing && matches(binding, d3.event)) {
 
6643     function capture() {
 
6648         var tagName = d3.select(d3.event.target).node().tagName;
 
6649         if (tagName == 'INPUT' || tagName == 'SELECT' || tagName == 'TEXTAREA') {
 
6652         testBindings(false);
 
6655     function keybinding(selection) {
 
6656         selection = selection || d3.select(document);
 
6657         selection.on('keydown.capture' + namespace, capture, true);
 
6658         selection.on('keydown.bubble' + namespace, bubble, false);
 
6662     keybinding.off = function(selection) {
 
6664         selection = selection || d3.select(document);
 
6665         selection.on('keydown.capture' + namespace, null);
 
6666         selection.on('keydown.bubble' + namespace, null);
 
6670     keybinding.on = function(code, callback, capture) {
 
6683         code = code.toLowerCase().match(/(?:(?:[^+⇧⌃⌥⌘])+|[⇧⌃⌥⌘]|\+\+|^\+$)/g);
 
6685         for (var i = 0; i < code.length; i++) {
 
6686             // Normalise matching errors
 
6687             if (code[i] === '++') code[i] = '+';
 
6689             if (code[i] in d3.keybinding.modifierCodes) {
 
6690                 binding.event[d3.keybinding.modifierProperties[d3.keybinding.modifierCodes[code[i]]]] = true;
 
6691             } else if (code[i] in d3.keybinding.keyCodes) {
 
6692                 binding.event.keyCode = d3.keybinding.keyCodes[code[i]];
 
6696         bindings.push(binding);
 
6705     d3.keybinding.modifierCodes = {
 
6708         // CTRL key, on Mac: ⌃
 
6710         // ALT key, on Mac: ⌥ (Alt)
 
6711         '⌥': 18, alt: 18, option: 18,
 
6712         // META, on Mac: ⌘ (CMD), on Windows (Win), on Linux (Super)
 
6713         '⌘': 91, meta: 91, cmd: 91, 'super': 91, win: 91
 
6716     d3.keybinding.modifierProperties = {
 
6723     d3.keybinding.keyCodes = {
 
6724         // Backspace key, on Mac: ⌫ (Backspace)
 
6725         '⌫': 8, backspace: 8,
 
6726         // Tab Key, on Mac: ⇥ (Tab), on Windows ⇥⇥
 
6727         '⇥': 9, '⇆': 9, tab: 9,
 
6729         '↩': 13, 'return': 13, enter: 13, '⌅': 13,
 
6731         'pause': 19, 'pause-break': 19,
 
6733         '⇪': 20, caps: 20, 'caps-lock': 20,
 
6734         // Escape key, on Mac: ⎋, on Windows: Esc
 
6735         '⎋': 27, escape: 27, esc: 27,
 
6738         // Page-Up key, or pgup, on Mac: ↖
 
6739         '↖': 33, pgup: 33, 'page-up': 33,
 
6740         // Page-Down key, or pgdown, on Mac: ↘
 
6741         '↘': 34, pgdown: 34, 'page-down': 34,
 
6742         // END key, on Mac: ⇟
 
6744         // HOME key, on Mac: ⇞
 
6746         // Insert key, or ins
 
6747         ins: 45, insert: 45,
 
6748         // Delete key, on Mac: ⌦ (Delete)
 
6749         '⌦': 46, del: 46, 'delete': 46,
 
6750         // Left Arrow Key, or ←
 
6751         '←': 37, left: 37, 'arrow-left': 37,
 
6752         // Up Arrow Key, or ↑
 
6753         '↑': 38, up: 38, 'arrow-up': 38,
 
6754         // Right Arrow Key, or →
 
6755         '→': 39, right: 39, 'arrow-right': 39,
 
6756         // Up Arrow Key, or ↓
 
6757         '↓': 40, down: 40, 'arrow-down': 40,
 
6758         // odities, printing characters that come out wrong:
 
6761         // Num-Multiply, or *
 
6762         '*': 106, star: 106, asterisk: 106, multiply: 106,
 
6764         '+': 107, 'plus': 107,
 
6765         // Num-Subtract, or -
 
6766         '-': 109, subtract: 109,
 
6772         ';': 186, semicolon: 186,
 
6774         '=': 187, 'equals': 187,
 
6776         ',': 188, comma: 188,
 
6778         // Period, or ., or full-stop
 
6779         '.': 190, period: 190, 'full-stop': 190,
 
6780         // Slash, or /, or forward-slash
 
6781         '/': 191, slash: 191, 'forward-slash': 191,
 
6782         // Tick, or `, or back-quote
 
6783         '`': 192, tick: 192, 'back-quote': 192,
 
6784         // Open bracket, or [
 
6785         '[': 219, 'open-bracket': 219,
 
6787         '\\': 220, 'back-slash': 220,
 
6788         // Close backet, or ]
 
6789         ']': 221, 'close-bracket': 221,
 
6790         // Apostrophe, or Quote, or '
 
6791         '\'': 222, quote: 222, apostrophe: 222
 
6797         d3.keybinding.keyCodes['num-' + n] = i;
 
6804         d3.keybinding.keyCodes[n] = i;
 
6811         d3.keybinding.keyCodes['f' + n] = i;
 
6818         d3.keybinding.keyCodes[String.fromCharCode(i).toLowerCase()] = i;
 
6821 d3.selection.prototype.one = function (type, listener, capture) {
 
6822     var target = this, typeOnce = type + ".once";
 
6824         target.on(typeOnce, null);
 
6825         listener.apply(this, arguments);
 
6827     target.on(typeOnce, one, capture);
 
6830 d3.selection.prototype.dimensions = function (dimensions) {
 
6831     var refresh = (function(node) {
 
6832         var cr = node.getBoundingClientRect();
 
6833         prop = [cr.width, cr.height];
 
6834         this.property('__dimensions__', prop);
 
6838     var node = this.node();
 
6840     if (!arguments.length) {
 
6841         if (!node) return [0,0];
 
6842         return this.property('__dimensions__') || refresh(node);
 
6844     if (dimensions === null) {
 
6845         if (!node) return [0,0];
 
6846         return refresh(node);
 
6850         .property('__dimensions__', [dimensions[0], dimensions[1]])
 
6851         .attr({width: dimensions[0], height: dimensions[1]});
 
6853 d3.selection.prototype.trigger = function (type) {
 
6854     this.each(function() {
 
6855         var evt = document.createEvent('HTMLEvents');
 
6856         evt.initEvent(type, true, true);
 
6857         this.dispatchEvent(evt);
 
6860 // Tooltips and svg mask used to highlight certain features
 
6861 d3.curtain = function() {
 
6863     var event = d3.dispatch(),
 
6868     function curtain(selection) {
 
6870         surface = selection.append('svg')
 
6871             .attr('id', 'curtain')
 
6874                 'pointer-events': 'none',
 
6875                 'position': 'absolute',
 
6880         darkness = surface.append('path')
 
6884                 'class': 'curtain-darkness'
 
6887         d3.select(window).on('resize.curtain', resize);
 
6889         tooltip = selection.append('div')
 
6890             .attr('class', 'tooltip')
 
6891             .style('z-index', 1002);
 
6893         tooltip.append('div').attr('class', 'tooltip-arrow');
 
6894         tooltip.append('div').attr('class', 'tooltip-inner');
 
6900                 width: window.innerWidth,
 
6901                 height: window.innerHeight
 
6903             curtain.cut(darkness.datum());
 
6907     curtain.reveal = function(box, text, tooltipclass, duration) {
 
6908         if (typeof box === 'string') box = d3.select(box).node();
 
6909         if (box.getBoundingClientRect) box = box.getBoundingClientRect();
 
6911         curtain.cut(box, duration);
 
6914             // pseudo markdown bold text hack
 
6915             var parts = text.split('**');
 
6916             var html = parts[0] ? '<span>' + parts[0] + '</span>' : '';
 
6917             if (parts[1]) html += '<span class="bold">' + parts[1] + '</span>';
 
6919             var dimensions = tooltip.classed('in', true)
 
6920                 .select('.tooltip-inner')
 
6926             var w = window.innerWidth,
 
6927                 h = window.innerHeight;
 
6929             if (box.top + box.height < Math.min(100, box.width + box.left)) {
 
6931                 pos = [box.left + box.width / 2 - dimensions[0]/ 2, box.top + box.height];
 
6933             } else if (box.left + box.width + 300 < window.innerWidth) {
 
6935                 pos = [box.left + box.width, box.top + box.height / 2 - dimensions[1] / 2];
 
6937             } else if (box.left > 300) {
 
6939                 pos = [box.left - 200, box.top + box.height / 2 - dimensions[1] / 2];
 
6942                 pos = [box.left, box.top + box.height];
 
6946                 Math.min(Math.max(10, pos[0]), w - dimensions[0] - 10),
 
6947                 Math.min(Math.max(10, pos[1]), h - dimensions[1] - 10)
 
6951             if (duration !== 0 || !tooltip.classed(side)) tooltip.call(iD.ui.Toggle(true));
 
6954                 .style('top', pos[1] + 'px')
 
6955                 .style('left', pos[0] + 'px')
 
6956                 .attr('class', 'curtain-tooltip tooltip in ' + side + ' ' + tooltipclass)
 
6957                 .select('.tooltip-inner')
 
6961             tooltip.call(iD.ui.Toggle(false));
 
6965     curtain.cut = function(datum, duration) {
 
6966         darkness.datum(datum);
 
6968         (duration === 0 ? darkness : darkness.transition().duration(duration || 600))
 
6969             .attr('d', function(d) {
 
6970                 var string = "M 0,0 L 0," + window.innerHeight + " L " +
 
6971                     window.innerWidth + "," + window.innerHeight + "L" +
 
6972                     window.innerWidth + ",0 Z";
 
6974                 if (!d) return string;
 
6975                 return string + 'M' +
 
6976                     d.left + ',' + d.top + 'L' +
 
6977                     d.left + ',' + (d.top + d.height) + 'L' +
 
6978                     (d.left + d.width) + ',' + (d.top + d.height) + 'L' +
 
6979                     (d.left + d.width) + ',' + (d.top) + 'Z';
 
6984     curtain.remove = function() {
 
6989     return d3.rebind(curtain, event, 'on');
 
6991 // Like selection.property('value', ...), but avoids no-op value sets,
 
6992 // which can result in layout/repaint thrashing in some situations.
 
6993 d3.selection.prototype.value = function(value) {
 
6994     function d3_selection_value(value) {
 
6995       function valueNull() {
 
6999       function valueConstant() {
 
7000         if (this.value !== value) this.value = value;
 
7003       function valueFunction() {
 
7004         var x = value.apply(this, arguments);
 
7005         if (x == null) delete this.value;
 
7006         else if (this.value !== x) this.value = x;
 
7009       return value == null
 
7010           ? valueNull : (typeof value === "function"
 
7011           ? valueFunction : valueConstant);
 
7014     if (!arguments.length) return this.property('value');
 
7015     return this.each(d3_selection_value(value));
 
7017 // Copyright (c) 2006, 2008 Tony Garnock-Jones <tonyg@lshift.net>
 
7018 // Copyright (c) 2006, 2008 LShift Ltd. <query@lshift.net>
 
7020 // Permission is hereby granted, free of charge, to any person
 
7021 // obtaining a copy of this software and associated documentation files
 
7022 // (the "Software"), to deal in the Software without restriction,
 
7023 // including without limitation the rights to use, copy, modify, merge,
 
7024 // publish, distribute, sublicense, and/or sell copies of the Software,
 
7025 // and to permit persons to whom the Software is furnished to do so,
 
7026 // subject to the following conditions:
 
7028 // The above copyright notice and this permission notice shall be
 
7029 // included in all copies or substantial portions of the Software.
 
7031 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 
7032 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 
7033 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 
7034 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
 
7035 // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 
7036 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
7037 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 
7040 // source:  https://bitbucket.org/lshift/synchrotron/src
 
7042 Diff3 = (function() {
 
7046         longest_common_subsequence: function(file1, file2) {
 
7047             /* Text diff algorithm following Hunt and McIlroy 1976.
 
7048              * J. W. Hunt and M. D. McIlroy, An algorithm for differential file
 
7049              * comparison, Bell Telephone Laboratories CSTR #41 (1976)
 
7050              * http://www.cs.dartmouth.edu/~doug/
 
7052              * Expects two arrays of strings.
 
7054             var equivalenceClasses;
 
7059             var c, i, j, jX, r, s;
 
7061             equivalenceClasses = {};
 
7062             for (j = 0; j < file2.length; j++) {
 
7064                 if (equivalenceClasses[line]) {
 
7065                     equivalenceClasses[line].push(j);
 
7067                     equivalenceClasses[line] = [j];
 
7071             candidates = [{file1index: -1,
 
7075             for (i = 0; i < file1.length; i++) {
 
7077                 file2indices = equivalenceClasses[line] || [];
 
7082                 for (jX = 0; jX < file2indices.length; jX++) {
 
7083                     j = file2indices[jX];
 
7085                     for (s = 0; s < candidates.length; s++) {
 
7086                         if ((candidates[s].file2index < j) &&
 
7087                             ((s == candidates.length - 1) ||
 
7088                              (candidates[s + 1].file2index > j)))
 
7092                     if (s < candidates.length) {
 
7093                         newCandidate = {file1index: i,
 
7095                                         chain: candidates[s]};
 
7096                         if (r == candidates.length) {
 
7103                         if (r == candidates.length) {
 
7104                             break; // no point in examining further (j)s
 
7112             // At this point, we know the LCS: it's in the reverse of the
 
7113             // linked-list through .chain of
 
7114             // candidates[candidates.length - 1].
 
7116             return candidates[candidates.length - 1];
 
7119         diff_comm: function(file1, file2) {
 
7120             // We apply the LCS to build a "comm"-style picture of the
 
7121             // differences between file1 and file2.
 
7124             var tail1 = file1.length;
 
7125             var tail2 = file2.length;
 
7126             var common = {common: []};
 
7128             function processCommon() {
 
7129                 if (common.common.length) {
 
7130                     common.common.reverse();
 
7131                     result.push(common);
 
7132                     common = {common: []};
 
7136             for (var candidate = Diff3.longest_common_subsequence(file1, file2);
 
7138                  candidate = candidate.chain)
 
7140                 var different = {file1: [], file2: []};
 
7142                 while (--tail1 > candidate.file1index) {
 
7143                     different.file1.push(file1[tail1]);
 
7146                 while (--tail2 > candidate.file2index) {
 
7147                     different.file2.push(file2[tail2]);
 
7150                 if (different.file1.length || different.file2.length) {
 
7152                     different.file1.reverse();
 
7153                     different.file2.reverse();
 
7154                     result.push(different);
 
7158                     common.common.push(file1[tail1]);
 
7168         diff_patch: function(file1, file2) {
 
7169             // We apply the LCD to build a JSON representation of a
 
7170             // diff(1)-style patch.
 
7173             var tail1 = file1.length;
 
7174             var tail2 = file2.length;
 
7176             function chunkDescription(file, offset, length) {
 
7178                 for (var i = 0; i < length; i++) {
 
7179                     chunk.push(file[offset + i]);
 
7181                 return {offset: offset,
 
7186             for (var candidate = Diff3.longest_common_subsequence(file1, file2);
 
7188                  candidate = candidate.chain)
 
7190                 var mismatchLength1 = tail1 - candidate.file1index - 1;
 
7191                 var mismatchLength2 = tail2 - candidate.file2index - 1;
 
7192                 tail1 = candidate.file1index;
 
7193                 tail2 = candidate.file2index;
 
7195                 if (mismatchLength1 || mismatchLength2) {
 
7196                     result.push({file1: chunkDescription(file1,
 
7197                                                          candidate.file1index + 1,
 
7199                                  file2: chunkDescription(file2,
 
7200                                                          candidate.file2index + 1,
 
7209         strip_patch: function(patch) {
 
7210         // Takes the output of Diff3.diff_patch(), and removes
 
7211         // information from it. It can still be used by patch(),
 
7212         // below, but can no longer be inverted.
 
7214         for (var i = 0; i < patch.length; i++) {
 
7215             var chunk = patch[i];
 
7216             newpatch.push({file1: {offset: chunk.file1.offset,
 
7217                        length: chunk.file1.length},
 
7218                    file2: {chunk: chunk.file2.chunk}});
 
7223         invert_patch: function(patch) {
 
7224             // Takes the output of Diff3.diff_patch(), and inverts the
 
7225             // sense of it, so that it can be applied to file2 to give
 
7226             // file1 rather than the other way around.
 
7228             for (var i = 0; i < patch.length; i++) {
 
7229                 var chunk = patch[i];
 
7230                 var tmp = chunk.file1;
 
7231                 chunk.file1 = chunk.file2;
 
7236         patch: function (file, patch) {
 
7237             // Applies a patch to a file.
 
7239             // Given file1 and file2, Diff3.patch(file1,
 
7240             // Diff3.diff_patch(file1, file2)) should give file2.
 
7243             var commonOffset = 0;
 
7245             function copyCommon(targetOffset) {
 
7246                 while (commonOffset < targetOffset) {
 
7247                     result.push(file[commonOffset]);
 
7252             for (var chunkIndex = 0; chunkIndex < patch.length; chunkIndex++) {
 
7253                 var chunk = patch[chunkIndex];
 
7254                 copyCommon(chunk.file1.offset);
 
7255                 for (var lineIndex = 0; lineIndex < chunk.file2.chunk.length; lineIndex++) {
 
7256                     result.push(chunk.file2.chunk[lineIndex]);
 
7258                 commonOffset += chunk.file1.length;
 
7261             copyCommon(file.length);
 
7265         diff_indices: function(file1, file2) {
 
7266             // We apply the LCS to give a simple representation of the
 
7267             // offsets and lengths of mismatched chunks in the input
 
7268             // files. This is used by diff3_merge_indices below.
 
7271             var tail1 = file1.length;
 
7272             var tail2 = file2.length;
 
7274             for (var candidate = Diff3.longest_common_subsequence(file1, file2);
 
7276                  candidate = candidate.chain)
 
7278                 var mismatchLength1 = tail1 - candidate.file1index - 1;
 
7279                 var mismatchLength2 = tail2 - candidate.file2index - 1;
 
7280                 tail1 = candidate.file1index;
 
7281                 tail2 = candidate.file2index;
 
7283                 if (mismatchLength1 || mismatchLength2) {
 
7284                     result.push({file1: [tail1 + 1, mismatchLength1],
 
7285                                  file2: [tail2 + 1, mismatchLength2]});
 
7293         diff3_merge_indices: function (a, o, b) {
 
7294             // Given three files, A, O, and B, where both A and B are
 
7295             // independently derived from O, returns a fairly complicated
 
7296             // internal representation of merge decisions it's taken. The
 
7297             // interested reader may wish to consult
 
7299             // Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce. "A
 
7300             // Formal Investigation of Diff3." In Arvind and Prasad,
 
7301             // editors, Foundations of Software Technology and Theoretical
 
7302             // Computer Science (FSTTCS), December 2007.
 
7304             // (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf)
 
7307             var m1 = Diff3.diff_indices(o, a);
 
7308             var m2 = Diff3.diff_indices(o, b);
 
7311             function addHunk(h, side) {
 
7312                 hunks.push([h.file1[0], side, h.file1[1], h.file2[0], h.file2[1]]);
 
7314             for (i = 0; i < m1.length; i++) { addHunk(m1[i], 0); }
 
7315             for (i = 0; i < m2.length; i++) { addHunk(m2[i], 2); }
 
7319             var commonOffset = 0;
 
7320             function copyCommon(targetOffset) {
 
7321                 if (targetOffset > commonOffset) {
 
7322                     result.push([1, commonOffset, targetOffset - commonOffset]);
 
7323                     commonOffset = targetOffset;
 
7327             for (var hunkIndex = 0; hunkIndex < hunks.length; hunkIndex++) {
 
7328                 var firstHunkIndex = hunkIndex;
 
7329                 var hunk = hunks[hunkIndex];
 
7330                 var regionLhs = hunk[0];
 
7331                 var regionRhs = regionLhs + hunk[2];
 
7332                 while (hunkIndex < hunks.length - 1) {
 
7333                     var maybeOverlapping = hunks[hunkIndex + 1];
 
7334                     var maybeLhs = maybeOverlapping[0];
 
7335                     if (maybeLhs > regionRhs) break;
 
7336                     regionRhs = maybeLhs + maybeOverlapping[2];
 
7340                 copyCommon(regionLhs);
 
7341                 if (firstHunkIndex == hunkIndex) {
 
7342             // The "overlap" was only one hunk long, meaning that
 
7343             // there's no conflict here. Either a and o were the
 
7344             // same, or b and o were the same.
 
7346                         result.push([hunk[1], hunk[3], hunk[4]]);
 
7349             // A proper conflict. Determine the extents of the
 
7350             // regions involved from a, o and b. Effectively merge
 
7351             // all the hunks on the left into one giant hunk, and
 
7352             // do the same for the right; then, correct for skew
 
7353             // in the regions of o that each side changed, and
 
7354             // report appropriate spans for the three sides.
 
7356                 0: [a.length, -1, o.length, -1],
 
7357                 2: [b.length, -1, o.length, -1]
 
7359                     for (i = firstHunkIndex; i <= hunkIndex; i++) {
 
7362                 var r = regions[side];
 
7364                 var oRhs = oLhs + hunk[2];
 
7365                         var abLhs = hunk[3];
 
7366                         var abRhs = abLhs + hunk[4];
 
7367                 r[0] = Math.min(abLhs, r[0]);
 
7368                 r[1] = Math.max(abRhs, r[1]);
 
7369                 r[2] = Math.min(oLhs, r[2]);
 
7370                 r[3] = Math.max(oRhs, r[3]);
 
7372             var aLhs = regions[0][0] + (regionLhs - regions[0][2]);
 
7373             var aRhs = regions[0][1] + (regionRhs - regions[0][3]);
 
7374             var bLhs = regions[2][0] + (regionLhs - regions[2][2]);
 
7375             var bRhs = regions[2][1] + (regionRhs - regions[2][3]);
 
7378                      regionLhs, regionRhs - regionLhs,
 
7379                      bLhs,      bRhs      - bLhs]);
 
7381                 commonOffset = regionRhs;
 
7384             copyCommon(o.length);
 
7388         diff3_merge: function (a, o, b, excludeFalseConflicts) {
 
7389             // Applies the output of Diff3.diff3_merge_indices to actually
 
7390             // construct the merged file; the returned result alternates
 
7391             // between "ok" and "conflict" blocks.
 
7394             var files = [a, o, b];
 
7395             var indices = Diff3.diff3_merge_indices(a, o, b);
 
7398             function flushOk() {
 
7399                 if (okLines.length) {
 
7400                     result.push({ok: okLines});
 
7404             function pushOk(xs) {
 
7405                 for (var j = 0; j < xs.length; j++) {
 
7406                     okLines.push(xs[j]);
 
7410             function isTrueConflict(rec) {
 
7411                 if (rec[2] != rec[6]) return true;
 
7414                 for (var j = 0; j < rec[2]; j++) {
 
7415                     if (a[j + aoff] != b[j + boff]) return true;
 
7420             for (var i = 0; i < indices.length; i++) {
 
7424                     if (excludeFalseConflicts && !isTrueConflict(x)) {
 
7425                         pushOk(files[0].slice(x[1], x[1] + x[2]));
 
7428                         result.push({conflict: {a: a.slice(x[1], x[1] + x[2]),
 
7430                                                 o: o.slice(x[3], x[3] + x[4]),
 
7432                                                 b: b.slice(x[5], x[5] + x[6]),
 
7436                     pushOk(files[side].slice(x[1], x[1] + x[2]));
 
7447 if (typeof module !== 'undefined') module.exports = Diff3;
 
7448 var JXON = new (function () {
 
7450     sValueProp = "keyValue", sAttributesProp = "keyAttributes", sAttrPref = "@", /* you can customize these values */
 
7451     aCache = [], rIsNull = /^\s*$/, rIsBool = /^(?:true|false)$/i;
 
7453   function parseText (sValue) {
 
7454     if (rIsNull.test(sValue)) { return null; }
 
7455     if (rIsBool.test(sValue)) { return sValue.toLowerCase() === "true"; }
 
7456     if (isFinite(sValue)) { return parseFloat(sValue); }
 
7457     if (isFinite(Date.parse(sValue))) { return new Date(sValue); }
 
7461   function EmptyTree () { }
 
7462   EmptyTree.prototype.toString = function () { return "null"; };
 
7463   EmptyTree.prototype.valueOf = function () { return null; };
 
7465   function objectify (vValue) {
 
7466     return vValue === null ? new EmptyTree() : vValue instanceof Object ? vValue : new vValue.constructor(vValue);
 
7469   function createObjTree (oParentNode, nVerb, bFreeze, bNesteAttr) {
 
7471       nLevelStart = aCache.length, bChildren = oParentNode.hasChildNodes(),
 
7472       bAttributes = oParentNode.hasAttributes(), bHighVerb = Boolean(nVerb & 2);
 
7475       sProp, vContent, nLength = 0, sCollectedTxt = "",
 
7476       vResult = bHighVerb ? {} : /* put here the default value for empty nodes: */ true;
 
7479       for (var oNode, nItem = 0; nItem < oParentNode.childNodes.length; nItem++) {
 
7480         oNode = oParentNode.childNodes.item(nItem);
 
7481         if (oNode.nodeType === 4) { sCollectedTxt += oNode.nodeValue; } /* nodeType is "CDATASection" (4) */
 
7482         else if (oNode.nodeType === 3) { sCollectedTxt += oNode.nodeValue.trim(); } /* nodeType is "Text" (3) */
 
7483         else if (oNode.nodeType === 1 && !oNode.prefix) { aCache.push(oNode); } /* nodeType is "Element" (1) */
 
7487     var nLevelEnd = aCache.length, vBuiltVal = parseText(sCollectedTxt);
 
7489     if (!bHighVerb && (bChildren || bAttributes)) { vResult = nVerb === 0 ? objectify(vBuiltVal) : {}; }
 
7491     for (var nElId = nLevelStart; nElId < nLevelEnd; nElId++) {
 
7492       sProp = aCache[nElId].nodeName.toLowerCase();
 
7493       vContent = createObjTree(aCache[nElId], nVerb, bFreeze, bNesteAttr);
 
7494       if (vResult.hasOwnProperty(sProp)) {
 
7495         if (vResult[sProp].constructor !== Array) { vResult[sProp] = [vResult[sProp]]; }
 
7496         vResult[sProp].push(vContent);
 
7498         vResult[sProp] = vContent;
 
7505         nAttrLen = oParentNode.attributes.length,
 
7506         sAPrefix = bNesteAttr ? "" : sAttrPref, oAttrParent = bNesteAttr ? {} : vResult;
 
7508       for (var oAttrib, nAttrib = 0; nAttrib < nAttrLen; nLength++, nAttrib++) {
 
7509         oAttrib = oParentNode.attributes.item(nAttrib);
 
7510         oAttrParent[sAPrefix + oAttrib.name.toLowerCase()] = parseText(oAttrib.value.trim());
 
7514         if (bFreeze) { Object.freeze(oAttrParent); }
 
7515         vResult[sAttributesProp] = oAttrParent;
 
7516         nLength -= nAttrLen - 1;
 
7520     if (nVerb === 3 || (nVerb === 2 || nVerb === 1 && nLength > 0) && sCollectedTxt) {
 
7521       vResult[sValueProp] = vBuiltVal;
 
7522     } else if (!bHighVerb && nLength === 0 && sCollectedTxt) {
 
7523       vResult = vBuiltVal;
 
7526     if (bFreeze && (bHighVerb || nLength > 0)) { Object.freeze(vResult); }
 
7528     aCache.length = nLevelStart;
 
7533   function loadObjTree (oXMLDoc, oParentEl, oParentObj) {
 
7536     if (oParentObj instanceof String || oParentObj instanceof Number || oParentObj instanceof Boolean) {
 
7537       oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toString())); /* verbosity level is 0 */
 
7538     } else if (oParentObj.constructor === Date) {
 
7539       oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toGMTString()));    
 
7542     for (var sName in oParentObj) {
 
7543       vValue = oParentObj[sName];
 
7544       if (isFinite(sName) || vValue instanceof Function) { continue; } /* verbosity level is 0 */
 
7545       if (sName === sValueProp) {
 
7546         if (vValue !== null && vValue !== true) { oParentEl.appendChild(oXMLDoc.createTextNode(vValue.constructor === Date ? vValue.toGMTString() : String(vValue))); }
 
7547       } else if (sName === sAttributesProp) { /* verbosity level is 3 */
 
7548         for (var sAttrib in vValue) { oParentEl.setAttribute(sAttrib, vValue[sAttrib]); }
 
7549       } else if (sName.charAt(0) === sAttrPref) {
 
7550         oParentEl.setAttribute(sName.slice(1), vValue);
 
7551       } else if (vValue.constructor === Array) {
 
7552         for (var nItem = 0; nItem < vValue.length; nItem++) {
 
7553           oChild = oXMLDoc.createElement(sName);
 
7554           loadObjTree(oXMLDoc, oChild, vValue[nItem]);
 
7555           oParentEl.appendChild(oChild);
 
7558         oChild = oXMLDoc.createElement(sName);
 
7559         if (vValue instanceof Object) {
 
7560           loadObjTree(oXMLDoc, oChild, vValue);
 
7561         } else if (vValue !== null && vValue !== true) {
 
7562           oChild.appendChild(oXMLDoc.createTextNode(vValue.toString()));
 
7564         oParentEl.appendChild(oChild);
 
7569   this.build = function (oXMLParent, nVerbosity /* optional */, bFreeze /* optional */, bNesteAttributes /* optional */) {
 
7570     var _nVerb = arguments.length > 1 && typeof nVerbosity === "number" ? nVerbosity & 3 : /* put here the default verbosity level: */ 1;
 
7571     return createObjTree(oXMLParent, _nVerb, bFreeze || false, arguments.length > 3 ? bNesteAttributes : _nVerb === 3);    
 
7574   this.unbuild = function (oObjTree) {    
 
7575     var oNewDoc = document.implementation.createDocument("", "", null);
 
7576     loadObjTree(oNewDoc, oNewDoc, oObjTree);
 
7580   this.stringify = function (oObjTree) {
 
7581     return (new XMLSerializer()).serializeToString(JXON.unbuild(oObjTree));
 
7584 // var myObject = JXON.build(doc);
 
7585 // we got our javascript object! try: alert(JSON.stringify(myObject));
 
7587 // var newDoc = JXON.unbuild(myObject);
 
7588 // we got our Document instance! try: alert((new XMLSerializer()).serializeToString(newDoc));
 
7591  * lodash (Custom Build) <https://lodash.com/>
 
7592  * Build: `lodash --development --output js/lib/lodash.js include="includes,toPairs,assign,bind,chunk,clone,compact,debounce,difference,each,every,extend,filter,find,first,forEach,forOwn,groupBy,indexOf,intersection,isEmpty,isEqual,isFunction,keys,last,map,omit,reject,some,throttle,union,uniq,values,without,flatten,value,chain,cloneDeep,merge,pick,reduce" exports="global,node"`
 
7593  * Copyright jQuery Foundation and other contributors <https://jquery.org/>
 
7594  * Released under MIT license <https://lodash.com/license>
 
7595  * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
 
7596  * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
 
7600   /** Used as a safe reference for `undefined` in pre-ES5 environments. */
 
7603   /** Used as the semantic version number. */
 
7604   var VERSION = '4.12.0';
 
7606   /** Used as the size to enable large array optimizations. */
 
7607   var LARGE_ARRAY_SIZE = 200;
 
7609   /** Used as the `TypeError` message for "Functions" methods. */
 
7610   var FUNC_ERROR_TEXT = 'Expected a function';
 
7612   /** Used to stand-in for `undefined` hash values. */
 
7613   var HASH_UNDEFINED = '__lodash_hash_undefined__';
 
7615   /** Used as the internal argument placeholder. */
 
7616   var PLACEHOLDER = '__lodash_placeholder__';
 
7618   /** Used to compose bitmasks for wrapper metadata. */
 
7621       CURRY_BOUND_FLAG = 4,
 
7623       CURRY_RIGHT_FLAG = 16,
 
7625       PARTIAL_RIGHT_FLAG = 64,
 
7630   /** Used to compose bitmasks for comparison styles. */
 
7631   var UNORDERED_COMPARE_FLAG = 1,
 
7632       PARTIAL_COMPARE_FLAG = 2;
 
7634   /** Used to detect hot functions by number of calls within a span of milliseconds. */
 
7635   var HOT_COUNT = 150,
 
7638   /** Used to indicate the type of lazy iteratees. */
 
7639   var LAZY_FILTER_FLAG = 1,
 
7641       LAZY_WHILE_FLAG = 3;
 
7643   /** Used as references for various `Number` constants. */
 
7644   var INFINITY = 1 / 0,
 
7645       MAX_SAFE_INTEGER = 9007199254740991,
 
7646       MAX_INTEGER = 1.7976931348623157e+308,
 
7649   /** Used as references for the maximum length and index of an array. */
 
7650   var MAX_ARRAY_LENGTH = 4294967295;
 
7652   /** `Object#toString` result references. */
 
7653   var argsTag = '[object Arguments]',
 
7654       arrayTag = '[object Array]',
 
7655       boolTag = '[object Boolean]',
 
7656       dateTag = '[object Date]',
 
7657       errorTag = '[object Error]',
 
7658       funcTag = '[object Function]',
 
7659       genTag = '[object GeneratorFunction]',
 
7660       mapTag = '[object Map]',
 
7661       numberTag = '[object Number]',
 
7662       objectTag = '[object Object]',
 
7663       promiseTag = '[object Promise]',
 
7664       regexpTag = '[object RegExp]',
 
7665       setTag = '[object Set]',
 
7666       stringTag = '[object String]',
 
7667       symbolTag = '[object Symbol]',
 
7668       weakMapTag = '[object WeakMap]';
 
7670   var arrayBufferTag = '[object ArrayBuffer]',
 
7671       dataViewTag = '[object DataView]',
 
7672       float32Tag = '[object Float32Array]',
 
7673       float64Tag = '[object Float64Array]',
 
7674       int8Tag = '[object Int8Array]',
 
7675       int16Tag = '[object Int16Array]',
 
7676       int32Tag = '[object Int32Array]',
 
7677       uint8Tag = '[object Uint8Array]',
 
7678       uint8ClampedTag = '[object Uint8ClampedArray]',
 
7679       uint16Tag = '[object Uint16Array]',
 
7680       uint32Tag = '[object Uint32Array]';
 
7682   /** Used to match property names within property paths. */
 
7683   var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
 
7684       reIsPlainProp = /^\w*$/,
 
7685       rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]/g;
 
7688    * Used to match `RegExp`
 
7689    * [syntax characters](http://ecma-international.org/ecma-262/6.0/#sec-patterns).
 
7691   var reRegExpChar = /[\\^$.*+?()[\]{}|]/g;
 
7693   /** Used to match leading and trailing whitespace. */
 
7694   var reTrim = /^\s+|\s+$/g;
 
7696   /** Used to match backslashes in property paths. */
 
7697   var reEscapeChar = /\\(\\)?/g;
 
7699   /** Used to match `RegExp` flags from their coerced string values. */
 
7700   var reFlags = /\w*$/;
 
7702   /** Used to detect bad signed hexadecimal string values. */
 
7703   var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
 
7705   /** Used to detect binary string values. */
 
7706   var reIsBinary = /^0b[01]+$/i;
 
7708   /** Used to detect host constructors (Safari). */
 
7709   var reIsHostCtor = /^\[object .+?Constructor\]$/;
 
7711   /** Used to detect octal string values. */
 
7712   var reIsOctal = /^0o[0-7]+$/i;
 
7714   /** Used to detect unsigned integer values. */
 
7715   var reIsUint = /^(?:0|[1-9]\d*)$/;
 
7717   /** Used to compose unicode character classes. */
 
7718   var rsAstralRange = '\\ud800-\\udfff',
 
7719       rsComboMarksRange = '\\u0300-\\u036f\\ufe20-\\ufe23',
 
7720       rsComboSymbolsRange = '\\u20d0-\\u20f0',
 
7721       rsVarRange = '\\ufe0e\\ufe0f';
 
7723   /** Used to compose unicode capture groups. */
 
7724   var rsAstral = '[' + rsAstralRange + ']',
 
7725       rsCombo = '[' + rsComboMarksRange + rsComboSymbolsRange + ']',
 
7726       rsFitz = '\\ud83c[\\udffb-\\udfff]',
 
7727       rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
 
7728       rsNonAstral = '[^' + rsAstralRange + ']',
 
7729       rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
 
7730       rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
 
7733   /** Used to compose unicode regexes. */
 
7734   var reOptMod = rsModifier + '?',
 
7735       rsOptVar = '[' + rsVarRange + ']?',
 
7736       rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
 
7737       rsSeq = rsOptVar + reOptMod + rsOptJoin,
 
7738       rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
 
7740   /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
 
7741   var reComplexSymbol = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
 
7743   /** Used to identify `toStringTag` values of typed arrays. */
 
7744   var typedArrayTags = {};
 
7745   typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
 
7746   typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
 
7747   typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
 
7748   typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
 
7749   typedArrayTags[uint32Tag] = true;
 
7750   typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
 
7751   typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
 
7752   typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
 
7753   typedArrayTags[errorTag] = typedArrayTags[funcTag] =
 
7754   typedArrayTags[mapTag] = typedArrayTags[numberTag] =
 
7755   typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
 
7756   typedArrayTags[setTag] = typedArrayTags[stringTag] =
 
7757   typedArrayTags[weakMapTag] = false;
 
7759   /** Used to identify `toStringTag` values supported by `_.clone`. */
 
7760   var cloneableTags = {};
 
7761   cloneableTags[argsTag] = cloneableTags[arrayTag] =
 
7762   cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =
 
7763   cloneableTags[boolTag] = cloneableTags[dateTag] =
 
7764   cloneableTags[float32Tag] = cloneableTags[float64Tag] =
 
7765   cloneableTags[int8Tag] = cloneableTags[int16Tag] =
 
7766   cloneableTags[int32Tag] = cloneableTags[mapTag] =
 
7767   cloneableTags[numberTag] = cloneableTags[objectTag] =
 
7768   cloneableTags[regexpTag] = cloneableTags[setTag] =
 
7769   cloneableTags[stringTag] = cloneableTags[symbolTag] =
 
7770   cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
 
7771   cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
 
7772   cloneableTags[errorTag] = cloneableTags[funcTag] =
 
7773   cloneableTags[weakMapTag] = false;
 
7775   /** Used to determine if values are of the language type `Object`. */
 
7781   /** Built-in method references without a dependency on `root`. */
 
7782   var freeParseInt = parseInt;
 
7784   /** Detect free variable `exports`. */
 
7785   var freeExports = (objectTypes[typeof exports] && exports && !exports.nodeType)
 
7789   /** Detect free variable `module`. */
 
7790   var freeModule = (objectTypes[typeof module] && module && !module.nodeType)
 
7794   /** Detect the popular CommonJS extension `module.exports`. */
 
7795   var moduleExports = (freeModule && freeModule.exports === freeExports)
 
7799   /** Detect free variable `global` from Node.js. */
 
7800   var freeGlobal = checkGlobal(freeExports && freeModule && typeof global == 'object' && global);
 
7802   /** Detect free variable `self`. */
 
7803   var freeSelf = checkGlobal(objectTypes[typeof self] && self);
 
7805   /** Detect free variable `window`. */
 
7806   var freeWindow = checkGlobal(objectTypes[typeof window] && window);
 
7808   /** Detect `this` as the global object. */
 
7809   var thisGlobal = checkGlobal(objectTypes[typeof this] && this);
 
7812    * Used as a reference to the global object.
 
7814    * The `this` value is used if it's the global object to avoid Greasemonkey's
 
7815    * restricted `window` object, otherwise the `window` object is used.
 
7817   var root = freeGlobal ||
 
7818     ((freeWindow !== (thisGlobal && thisGlobal.window)) && freeWindow) ||
 
7819       freeSelf || thisGlobal || Function('return this')();
 
7821   /*--------------------------------------------------------------------------*/
 
7824    * Adds the key-value `pair` to `map`.
 
7827    * @param {Object} map The map to modify.
 
7828    * @param {Array} pair The key-value pair to add.
 
7829    * @returns {Object} Returns `map`.
 
7831   function addMapEntry(map, pair) {
 
7832     // Don't return `Map#set` because it doesn't return the map instance in IE 11.
 
7833     map.set(pair[0], pair[1]);
 
7838    * Adds `value` to `set`.
 
7841    * @param {Object} set The set to modify.
 
7842    * @param {*} value The value to add.
 
7843    * @returns {Object} Returns `set`.
 
7845   function addSetEntry(set, value) {
 
7851    * A faster alternative to `Function#apply`, this function invokes `func`
 
7852    * with the `this` binding of `thisArg` and the arguments of `args`.
 
7855    * @param {Function} func The function to invoke.
 
7856    * @param {*} thisArg The `this` binding of `func`.
 
7857    * @param {Array} args The arguments to invoke `func` with.
 
7858    * @returns {*} Returns the result of `func`.
 
7860   function apply(func, thisArg, args) {
 
7861     var length = args.length;
 
7863       case 0: return func.call(thisArg);
 
7864       case 1: return func.call(thisArg, args[0]);
 
7865       case 2: return func.call(thisArg, args[0], args[1]);
 
7866       case 3: return func.call(thisArg, args[0], args[1], args[2]);
 
7868     return func.apply(thisArg, args);
 
7872    * A specialized version of `baseAggregator` for arrays.
 
7875    * @param {Array} array The array to iterate over.
 
7876    * @param {Function} setter The function to set `accumulator` values.
 
7877    * @param {Function} iteratee The iteratee to transform keys.
 
7878    * @param {Object} accumulator The initial aggregated object.
 
7879    * @returns {Function} Returns `accumulator`.
 
7881   function arrayAggregator(array, setter, iteratee, accumulator) {
 
7883         length = array.length;
 
7885     while (++index < length) {
 
7886       var value = array[index];
 
7887       setter(accumulator, value, iteratee(value), array);
 
7893    * A specialized version of `_.forEach` for arrays without support for
 
7894    * iteratee shorthands.
 
7897    * @param {Array} array The array to iterate over.
 
7898    * @param {Function} iteratee The function invoked per iteration.
 
7899    * @returns {Array} Returns `array`.
 
7901   function arrayEach(array, iteratee) {
 
7903         length = array.length;
 
7905     while (++index < length) {
 
7906       if (iteratee(array[index], index, array) === false) {
 
7914    * A specialized version of `_.every` for arrays without support for
 
7915    * iteratee shorthands.
 
7918    * @param {Array} array The array to iterate over.
 
7919    * @param {Function} predicate The function invoked per iteration.
 
7920    * @returns {boolean} Returns `true` if all elements pass the predicate check,
 
7923   function arrayEvery(array, predicate) {
 
7925         length = array.length;
 
7927     while (++index < length) {
 
7928       if (!predicate(array[index], index, array)) {
 
7936    * A specialized version of `_.filter` for arrays without support for
 
7937    * iteratee shorthands.
 
7940    * @param {Array} array The array to iterate over.
 
7941    * @param {Function} predicate The function invoked per iteration.
 
7942    * @returns {Array} Returns the new filtered array.
 
7944   function arrayFilter(array, predicate) {
 
7946         length = array.length,
 
7950     while (++index < length) {
 
7951       var value = array[index];
 
7952       if (predicate(value, index, array)) {
 
7953         result[resIndex++] = value;
 
7960    * A specialized version of `_.includes` for arrays without support for
 
7961    * specifying an index to search from.
 
7964    * @param {Array} array The array to search.
 
7965    * @param {*} target The value to search for.
 
7966    * @returns {boolean} Returns `true` if `target` is found, else `false`.
 
7968   function arrayIncludes(array, value) {
 
7969     return !!array.length && baseIndexOf(array, value, 0) > -1;
 
7973    * This function is like `arrayIncludes` except that it accepts a comparator.
 
7976    * @param {Array} array The array to search.
 
7977    * @param {*} target The value to search for.
 
7978    * @param {Function} comparator The comparator invoked per element.
 
7979    * @returns {boolean} Returns `true` if `target` is found, else `false`.
 
7981   function arrayIncludesWith(array, value, comparator) {
 
7983         length = array.length;
 
7985     while (++index < length) {
 
7986       if (comparator(value, array[index])) {
 
7994    * A specialized version of `_.map` for arrays without support for iteratee
 
7998    * @param {Array} array The array to iterate over.
 
7999    * @param {Function} iteratee The function invoked per iteration.
 
8000    * @returns {Array} Returns the new mapped array.
 
8002   function arrayMap(array, iteratee) {
 
8004         length = array.length,
 
8005         result = Array(length);
 
8007     while (++index < length) {
 
8008       result[index] = iteratee(array[index], index, array);
 
8014    * Appends the elements of `values` to `array`.
 
8017    * @param {Array} array The array to modify.
 
8018    * @param {Array} values The values to append.
 
8019    * @returns {Array} Returns `array`.
 
8021   function arrayPush(array, values) {
 
8023         length = values.length,
 
8024         offset = array.length;
 
8026     while (++index < length) {
 
8027       array[offset + index] = values[index];
 
8033    * A specialized version of `_.reduce` for arrays without support for
 
8034    * iteratee shorthands.
 
8037    * @param {Array} array The array to iterate over.
 
8038    * @param {Function} iteratee The function invoked per iteration.
 
8039    * @param {*} [accumulator] The initial value.
 
8040    * @param {boolean} [initAccum] Specify using the first element of `array` as
 
8041    *  the initial value.
 
8042    * @returns {*} Returns the accumulated value.
 
8044   function arrayReduce(array, iteratee, accumulator, initAccum) {
 
8046         length = array.length;
 
8048     if (initAccum && length) {
 
8049       accumulator = array[++index];
 
8051     while (++index < length) {
 
8052       accumulator = iteratee(accumulator, array[index], index, array);
 
8058    * A specialized version of `_.some` for arrays without support for iteratee
 
8062    * @param {Array} array The array to iterate over.
 
8063    * @param {Function} predicate The function invoked per iteration.
 
8064    * @returns {boolean} Returns `true` if any element passes the predicate check,
 
8067   function arraySome(array, predicate) {
 
8069         length = array.length;
 
8071     while (++index < length) {
 
8072       if (predicate(array[index], index, array)) {
 
8080    * The base implementation of methods like `_.find` and `_.findKey`, without
 
8081    * support for iteratee shorthands, which iterates over `collection` using
 
8085    * @param {Array|Object} collection The collection to search.
 
8086    * @param {Function} predicate The function invoked per iteration.
 
8087    * @param {Function} eachFunc The function to iterate over `collection`.
 
8088    * @param {boolean} [retKey] Specify returning the key of the found element
 
8089    *  instead of the element itself.
 
8090    * @returns {*} Returns the found element or its key, else `undefined`.
 
8092   function baseFind(collection, predicate, eachFunc, retKey) {
 
8094     eachFunc(collection, function(value, key, collection) {
 
8095       if (predicate(value, key, collection)) {
 
8096         result = retKey ? key : value;
 
8104    * The base implementation of `_.findIndex` and `_.findLastIndex` without
 
8105    * support for iteratee shorthands.
 
8108    * @param {Array} array The array to search.
 
8109    * @param {Function} predicate The function invoked per iteration.
 
8110    * @param {boolean} [fromRight] Specify iterating from right to left.
 
8111    * @returns {number} Returns the index of the matched value, else `-1`.
 
8113   function baseFindIndex(array, predicate, fromRight) {
 
8114     var length = array.length,
 
8115         index = fromRight ? length : -1;
 
8117     while ((fromRight ? index-- : ++index < length)) {
 
8118       if (predicate(array[index], index, array)) {
 
8126    * The base implementation of `_.indexOf` without `fromIndex` bounds checks.
 
8129    * @param {Array} array The array to search.
 
8130    * @param {*} value The value to search for.
 
8131    * @param {number} fromIndex The index to search from.
 
8132    * @returns {number} Returns the index of the matched value, else `-1`.
 
8134   function baseIndexOf(array, value, fromIndex) {
 
8135     if (value !== value) {
 
8136       return indexOfNaN(array, fromIndex);
 
8138     var index = fromIndex - 1,
 
8139         length = array.length;
 
8141     while (++index < length) {
 
8142       if (array[index] === value) {
 
8150    * The base implementation of `_.reduce` and `_.reduceRight`, without support
 
8151    * for iteratee shorthands, which iterates over `collection` using `eachFunc`.
 
8154    * @param {Array|Object} collection The collection to iterate over.
 
8155    * @param {Function} iteratee The function invoked per iteration.
 
8156    * @param {*} accumulator The initial value.
 
8157    * @param {boolean} initAccum Specify using the first or last element of
 
8158    *  `collection` as the initial value.
 
8159    * @param {Function} eachFunc The function to iterate over `collection`.
 
8160    * @returns {*} Returns the accumulated value.
 
8162   function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
 
8163     eachFunc(collection, function(value, index, collection) {
 
8164       accumulator = initAccum
 
8165         ? (initAccum = false, value)
 
8166         : iteratee(accumulator, value, index, collection);
 
8172    * The base implementation of `_.times` without support for iteratee shorthands
 
8173    * or max array length checks.
 
8176    * @param {number} n The number of times to invoke `iteratee`.
 
8177    * @param {Function} iteratee The function invoked per iteration.
 
8178    * @returns {Array} Returns the array of results.
 
8180   function baseTimes(n, iteratee) {
 
8184     while (++index < n) {
 
8185       result[index] = iteratee(index);
 
8191    * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array
 
8192    * of key-value pairs for `object` corresponding to the property names of `props`.
 
8195    * @param {Object} object The object to query.
 
8196    * @param {Array} props The property names to get values for.
 
8197    * @returns {Object} Returns the key-value pairs.
 
8199   function baseToPairs(object, props) {
 
8200     return arrayMap(props, function(key) {
 
8201       return [key, object[key]];
 
8206    * The base implementation of `_.unary` without support for storing wrapper metadata.
 
8209    * @param {Function} func The function to cap arguments for.
 
8210    * @returns {Function} Returns the new capped function.
 
8212   function baseUnary(func) {
 
8213     return function(value) {
 
8219    * The base implementation of `_.values` and `_.valuesIn` which creates an
 
8220    * array of `object` property values corresponding to the property names
 
8224    * @param {Object} object The object to query.
 
8225    * @param {Array} props The property names to get values for.
 
8226    * @returns {Object} Returns the array of property values.
 
8228   function baseValues(object, props) {
 
8229     return arrayMap(props, function(key) {
 
8235    * Checks if a cache value for `key` exists.
 
8238    * @param {Object} cache The cache to query.
 
8239    * @param {string} key The key of the entry to check.
 
8240    * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 
8242   function cacheHas(cache, key) {
 
8243     return cache.has(key);
 
8247    * Checks if `value` is a global object.
 
8250    * @param {*} value The value to check.
 
8251    * @returns {null|Object} Returns `value` if it's a global object, else `null`.
 
8253   function checkGlobal(value) {
 
8254     return (value && value.Object === Object) ? value : null;
 
8258    * Gets the number of `placeholder` occurrences in `array`.
 
8261    * @param {Array} array The array to inspect.
 
8262    * @param {*} placeholder The placeholder to search for.
 
8263    * @returns {number} Returns the placeholder count.
 
8265   function countHolders(array, placeholder) {
 
8266     var length = array.length,
 
8270       if (array[length] === placeholder) {
 
8278    * Gets the index at which the first occurrence of `NaN` is found in `array`.
 
8281    * @param {Array} array The array to search.
 
8282    * @param {number} fromIndex The index to search from.
 
8283    * @param {boolean} [fromRight] Specify iterating from right to left.
 
8284    * @returns {number} Returns the index of the matched `NaN`, else `-1`.
 
8286   function indexOfNaN(array, fromIndex, fromRight) {
 
8287     var length = array.length,
 
8288         index = fromIndex + (fromRight ? 0 : -1);
 
8290     while ((fromRight ? index-- : ++index < length)) {
 
8291       var other = array[index];
 
8292       if (other !== other) {
 
8300    * Checks if `value` is a host object in IE < 9.
 
8303    * @param {*} value The value to check.
 
8304    * @returns {boolean} Returns `true` if `value` is a host object, else `false`.
 
8306   function isHostObject(value) {
 
8307     // Many host objects are `Object` objects that can coerce to strings
 
8308     // despite having improperly defined `toString` methods.
 
8310     if (value != null && typeof value.toString != 'function') {
 
8312         result = !!(value + '');
 
8319    * Converts `iterator` to an array.
 
8322    * @param {Object} iterator The iterator to convert.
 
8323    * @returns {Array} Returns the converted array.
 
8325   function iteratorToArray(iterator) {
 
8329     while (!(data = iterator.next()).done) {
 
8330       result.push(data.value);
 
8336    * Converts `map` to its key-value pairs.
 
8339    * @param {Object} map The map to convert.
 
8340    * @returns {Array} Returns the key-value pairs.
 
8342   function mapToArray(map) {
 
8344         result = Array(map.size);
 
8346     map.forEach(function(value, key) {
 
8347       result[++index] = [key, value];
 
8353    * Replaces all `placeholder` elements in `array` with an internal placeholder
 
8354    * and returns an array of their indexes.
 
8357    * @param {Array} array The array to modify.
 
8358    * @param {*} placeholder The placeholder to replace.
 
8359    * @returns {Array} Returns the new array of placeholder indexes.
 
8361   function replaceHolders(array, placeholder) {
 
8363         length = array.length,
 
8367     while (++index < length) {
 
8368       var value = array[index];
 
8369       if (value === placeholder || value === PLACEHOLDER) {
 
8370         array[index] = PLACEHOLDER;
 
8371         result[resIndex++] = index;
 
8378    * Converts `set` to an array of its values.
 
8381    * @param {Object} set The set to convert.
 
8382    * @returns {Array} Returns the values.
 
8384   function setToArray(set) {
 
8386         result = Array(set.size);
 
8388     set.forEach(function(value) {
 
8389       result[++index] = value;
 
8395    * Converts `set` to its value-value pairs.
 
8398    * @param {Object} set The set to convert.
 
8399    * @returns {Array} Returns the value-value pairs.
 
8401   function setToPairs(set) {
 
8403         result = Array(set.size);
 
8405     set.forEach(function(value) {
 
8406       result[++index] = [value, value];
 
8412    * Converts `string` to an array.
 
8415    * @param {string} string The string to convert.
 
8416    * @returns {Array} Returns the converted array.
 
8418   function stringToArray(string) {
 
8419     return string.match(reComplexSymbol);
 
8422   /*--------------------------------------------------------------------------*/
 
8424   /** Used for built-in method references. */
 
8425   var arrayProto = Array.prototype,
 
8426       objectProto = Object.prototype;
 
8428   /** Used to resolve the decompiled source of functions. */
 
8429   var funcToString = Function.prototype.toString;
 
8431   /** Used to check objects for own properties. */
 
8432   var hasOwnProperty = objectProto.hasOwnProperty;
 
8434   /** Used to infer the `Object` constructor. */
 
8435   var objectCtorString = funcToString.call(Object);
 
8438    * Used to resolve the
 
8439    * [`toStringTag`](http://ecma-international.org/ecma-262/6.0/#sec-object.prototype.tostring)
 
8442   var objectToString = objectProto.toString;
 
8444   /** Used to detect if a method is native. */
 
8445   var reIsNative = RegExp('^' +
 
8446     funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
 
8447     .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
 
8450   /** Built-in value references. */
 
8451   var Buffer = moduleExports ? root.Buffer : undefined,
 
8452       Reflect = root.Reflect,
 
8453       Symbol = root.Symbol,
 
8454       Uint8Array = root.Uint8Array,
 
8455       enumerate = Reflect ? Reflect.enumerate : undefined,
 
8456       getOwnPropertySymbols = Object.getOwnPropertySymbols,
 
8457       iteratorSymbol = typeof (iteratorSymbol = Symbol && Symbol.iterator) == 'symbol' ? iteratorSymbol : undefined,
 
8458       objectCreate = Object.create,
 
8459       propertyIsEnumerable = objectProto.propertyIsEnumerable,
 
8460       splice = arrayProto.splice;
 
8462   /* Built-in method references for those with the same name as other `lodash` methods. */
 
8463   var nativeCeil = Math.ceil,
 
8464       nativeGetPrototype = Object.getPrototypeOf,
 
8465       nativeKeys = Object.keys,
 
8466       nativeMax = Math.max,
 
8467       nativeMin = Math.min,
 
8468       nativeReverse = arrayProto.reverse;
 
8470   /* Built-in method references that are verified to be native. */
 
8471   var DataView = getNative(root, 'DataView'),
 
8472       Map = getNative(root, 'Map'),
 
8473       Promise = getNative(root, 'Promise'),
 
8474       Set = getNative(root, 'Set'),
 
8475       WeakMap = getNative(root, 'WeakMap'),
 
8476       nativeCreate = getNative(Object, 'create');
 
8478   /** Used to store function metadata. */
 
8479   var metaMap = WeakMap && new WeakMap;
 
8481   /** Detect if properties shadowing those on `Object.prototype` are non-enumerable. */
 
8482   var nonEnumShadows = !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf');
 
8484   /** Used to lookup unminified function names. */
 
8487   /** Used to detect maps, sets, and weakmaps. */
 
8488   var dataViewCtorString = toSource(DataView),
 
8489       mapCtorString = toSource(Map),
 
8490       promiseCtorString = toSource(Promise),
 
8491       setCtorString = toSource(Set),
 
8492       weakMapCtorString = toSource(WeakMap);
 
8494   /** Used to convert symbols to primitives and strings. */
 
8495   var symbolProto = Symbol ? Symbol.prototype : undefined,
 
8496       symbolValueOf = symbolProto ? symbolProto.valueOf : undefined,
 
8497       symbolToString = symbolProto ? symbolProto.toString : undefined;
 
8499   /*------------------------------------------------------------------------*/
 
8502    * Creates a `lodash` object which wraps `value` to enable implicit method
 
8503    * chain sequences. Methods that operate on and return arrays, collections,
 
8504    * and functions can be chained together. Methods that retrieve a single value
 
8505    * or may return a primitive value will automatically end the chain sequence
 
8506    * and return the unwrapped value. Otherwise, the value must be unwrapped
 
8509    * Explicit chain sequences, which must be unwrapped with `_#value`, may be
 
8510    * enabled using `_.chain`.
 
8512    * The execution of chained methods is lazy, that is, it's deferred until
 
8513    * `_#value` is implicitly or explicitly called.
 
8515    * Lazy evaluation allows several methods to support shortcut fusion.
 
8516    * Shortcut fusion is an optimization to merge iteratee calls; this avoids
 
8517    * the creation of intermediate arrays and can greatly reduce the number of
 
8518    * iteratee executions. Sections of a chain sequence qualify for shortcut
 
8519    * fusion if the section is applied to an array of at least `200` elements
 
8520    * and any iteratees accept only one argument. The heuristic for whether a
 
8521    * section qualifies for shortcut fusion is subject to change.
 
8523    * Chaining is supported in custom builds as long as the `_#value` method is
 
8524    * directly or indirectly included in the build.
 
8526    * In addition to lodash methods, wrappers have `Array` and `String` methods.
 
8528    * The wrapper `Array` methods are:
 
8529    * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift`
 
8531    * The wrapper `String` methods are:
 
8532    * `replace` and `split`
 
8534    * The wrapper methods that support shortcut fusion are:
 
8535    * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`,
 
8536    * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`,
 
8537    * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`
 
8539    * The chainable wrapper methods are:
 
8540    * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,
 
8541    * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,
 
8542    * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,
 
8543    * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`,
 
8544    * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`,
 
8545    * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`,
 
8546    * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`,
 
8547    * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`,
 
8548    * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`,
 
8549    * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`,
 
8550    * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`,
 
8551    * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`,
 
8552    * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`,
 
8553    * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`,
 
8554    * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`,
 
8555    * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`,
 
8556    * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`,
 
8557    * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`,
 
8558    * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`,
 
8559    * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`,
 
8560    * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`,
 
8561    * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`,
 
8562    * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`,
 
8563    * `zipObject`, `zipObjectDeep`, and `zipWith`
 
8565    * The wrapper methods that are **not** chainable by default are:
 
8566    * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,
 
8567    * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `deburr`, `divide`, `each`,
 
8568    * `eachRight`, `endsWith`, `eq`, `escape`, `escapeRegExp`, `every`, `find`,
 
8569    * `findIndex`, `findKey`, `findLast`, `findLastIndex`, `findLastKey`, `first`,
 
8570    * `floor`, `forEach`, `forEachRight`, `forIn`, `forInRight`, `forOwn`,
 
8571    * `forOwnRight`, `get`, `gt`, `gte`, `has`, `hasIn`, `head`, `identity`,
 
8572    * `includes`, `indexOf`, `inRange`, `invoke`, `isArguments`, `isArray`,
 
8573    * `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`, `isBoolean`,
 
8574    * `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`, `isEqualWith`,
 
8575    * `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`, `isMap`,
 
8576    * `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`, `isNumber`,
 
8577    * `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`, `isSafeInteger`,
 
8578    * `isSet`, `isString`, `isUndefined`, `isTypedArray`, `isWeakMap`, `isWeakSet`,
 
8579    * `join`, `kebabCase`, `last`, `lastIndexOf`, `lowerCase`, `lowerFirst`,
 
8580    * `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`, `min`, `minBy`, `multiply`,
 
8581    * `noConflict`, `noop`, `now`, `nth`, `pad`, `padEnd`, `padStart`, `parseInt`,
 
8582    * `pop`, `random`, `reduce`, `reduceRight`, `repeat`, `result`, `round`,
 
8583    * `runInContext`, `sample`, `shift`, `size`, `snakeCase`, `some`, `sortedIndex`,
 
8584    * `sortedIndexBy`, `sortedLastIndex`, `sortedLastIndexBy`, `startCase`,
 
8585    * `startsWith`, `subtract`, `sum`, `sumBy`, `template`, `times`, `toFinite`,
 
8586    * `toInteger`, `toJSON`, `toLength`, `toLower`, `toNumber`, `toSafeInteger`,
 
8587    * `toString`, `toUpper`, `trim`, `trimEnd`, `trimStart`, `truncate`, `unescape`,
 
8588    * `uniqueId`, `upperCase`, `upperFirst`, `value`, and `words`
 
8593    * @param {*} value The value to wrap in a `lodash` instance.
 
8594    * @returns {Object} Returns the new `lodash` wrapper instance.
 
8597    * function square(n) {
 
8601    * var wrapped = _([1, 2, 3]);
 
8603    * // Returns an unwrapped value.
 
8604    * wrapped.reduce(_.add);
 
8607    * // Returns a wrapped value.
 
8608    * var squares = wrapped.map(square);
 
8610    * _.isArray(squares);
 
8613    * _.isArray(squares.value());
 
8616   function lodash(value) {
 
8617     if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
 
8618       if (value instanceof LodashWrapper) {
 
8621       if (hasOwnProperty.call(value, '__wrapped__')) {
 
8622         return wrapperClone(value);
 
8625     return new LodashWrapper(value);
 
8629    * The function whose prototype chain sequence wrappers inherit from.
 
8633   function baseLodash() {
 
8634     // No operation performed.
 
8638    * The base constructor for creating `lodash` wrapper objects.
 
8641    * @param {*} value The value to wrap.
 
8642    * @param {boolean} [chainAll] Enable explicit method chain sequences.
 
8644   function LodashWrapper(value, chainAll) {
 
8645     this.__wrapped__ = value;
 
8646     this.__actions__ = [];
 
8647     this.__chain__ = !!chainAll;
 
8649     this.__values__ = undefined;
 
8652   // Ensure wrappers are instances of `baseLodash`.
 
8653   lodash.prototype = baseLodash.prototype;
 
8654   lodash.prototype.constructor = lodash;
 
8656   LodashWrapper.prototype = baseCreate(baseLodash.prototype);
 
8657   LodashWrapper.prototype.constructor = LodashWrapper;
 
8659   /*------------------------------------------------------------------------*/
 
8662    * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
 
8666    * @param {*} value The value to wrap.
 
8668   function LazyWrapper(value) {
 
8669     this.__wrapped__ = value;
 
8670     this.__actions__ = [];
 
8672     this.__filtered__ = false;
 
8673     this.__iteratees__ = [];
 
8674     this.__takeCount__ = MAX_ARRAY_LENGTH;
 
8675     this.__views__ = [];
 
8679    * Creates a clone of the lazy wrapper object.
 
8683    * @memberOf LazyWrapper
 
8684    * @returns {Object} Returns the cloned `LazyWrapper` object.
 
8686   function lazyClone() {
 
8687     var result = new LazyWrapper(this.__wrapped__);
 
8688     result.__actions__ = copyArray(this.__actions__);
 
8689     result.__dir__ = this.__dir__;
 
8690     result.__filtered__ = this.__filtered__;
 
8691     result.__iteratees__ = copyArray(this.__iteratees__);
 
8692     result.__takeCount__ = this.__takeCount__;
 
8693     result.__views__ = copyArray(this.__views__);
 
8698    * Reverses the direction of lazy iteration.
 
8702    * @memberOf LazyWrapper
 
8703    * @returns {Object} Returns the new reversed `LazyWrapper` object.
 
8705   function lazyReverse() {
 
8706     if (this.__filtered__) {
 
8707       var result = new LazyWrapper(this);
 
8708       result.__dir__ = -1;
 
8709       result.__filtered__ = true;
 
8711       result = this.clone();
 
8712       result.__dir__ *= -1;
 
8718    * Extracts the unwrapped value from its lazy wrapper.
 
8722    * @memberOf LazyWrapper
 
8723    * @returns {*} Returns the unwrapped value.
 
8725   function lazyValue() {
 
8726     var array = this.__wrapped__.value(),
 
8728         isArr = isArray(array),
 
8730         arrLength = isArr ? array.length : 0,
 
8731         view = getView(0, arrLength, this.__views__),
 
8734         length = end - start,
 
8735         index = isRight ? end : (start - 1),
 
8736         iteratees = this.__iteratees__,
 
8737         iterLength = iteratees.length,
 
8739         takeCount = nativeMin(length, this.__takeCount__);
 
8741     if (!isArr || arrLength < LARGE_ARRAY_SIZE ||
 
8742         (arrLength == length && takeCount == length)) {
 
8743       return baseWrapperValue(array, this.__actions__);
 
8748     while (length-- && resIndex < takeCount) {
 
8752           value = array[index];
 
8754       while (++iterIndex < iterLength) {
 
8755         var data = iteratees[iterIndex],
 
8756             iteratee = data.iteratee,
 
8758             computed = iteratee(value);
 
8760         if (type == LAZY_MAP_FLAG) {
 
8762         } else if (!computed) {
 
8763           if (type == LAZY_FILTER_FLAG) {
 
8770       result[resIndex++] = value;
 
8775   // Ensure `LazyWrapper` is an instance of `baseLodash`.
 
8776   LazyWrapper.prototype = baseCreate(baseLodash.prototype);
 
8777   LazyWrapper.prototype.constructor = LazyWrapper;
 
8779   /*------------------------------------------------------------------------*/
 
8782    * Creates a hash object.
 
8786    * @param {Array} [entries] The key-value pairs to cache.
 
8788   function Hash(entries) {
 
8790         length = entries ? entries.length : 0;
 
8793     while (++index < length) {
 
8794       var entry = entries[index];
 
8795       this.set(entry[0], entry[1]);
 
8800    * Removes all key-value entries from the hash.
 
8806   function hashClear() {
 
8807     this.__data__ = nativeCreate ? nativeCreate(null) : {};
 
8811    * Removes `key` and its value from the hash.
 
8816    * @param {Object} hash The hash to modify.
 
8817    * @param {string} key The key of the value to remove.
 
8818    * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 
8820   function hashDelete(key) {
 
8821     return this.has(key) && delete this.__data__[key];
 
8825    * Gets the hash value for `key`.
 
8830    * @param {string} key The key of the value to get.
 
8831    * @returns {*} Returns the entry value.
 
8833   function hashGet(key) {
 
8834     var data = this.__data__;
 
8836       var result = data[key];
 
8837       return result === HASH_UNDEFINED ? undefined : result;
 
8839     return hasOwnProperty.call(data, key) ? data[key] : undefined;
 
8843    * Checks if a hash value for `key` exists.
 
8848    * @param {string} key The key of the entry to check.
 
8849    * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 
8851   function hashHas(key) {
 
8852     var data = this.__data__;
 
8853     return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key);
 
8857    * Sets the hash `key` to `value`.
 
8862    * @param {string} key The key of the value to set.
 
8863    * @param {*} value The value to set.
 
8864    * @returns {Object} Returns the hash instance.
 
8866   function hashSet(key, value) {
 
8867     var data = this.__data__;
 
8868     data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
 
8872   // Add methods to `Hash`.
 
8873   Hash.prototype.clear = hashClear;
 
8874   Hash.prototype['delete'] = hashDelete;
 
8875   Hash.prototype.get = hashGet;
 
8876   Hash.prototype.has = hashHas;
 
8877   Hash.prototype.set = hashSet;
 
8879   /*------------------------------------------------------------------------*/
 
8882    * Creates an list cache object.
 
8886    * @param {Array} [entries] The key-value pairs to cache.
 
8888   function ListCache(entries) {
 
8890         length = entries ? entries.length : 0;
 
8893     while (++index < length) {
 
8894       var entry = entries[index];
 
8895       this.set(entry[0], entry[1]);
 
8900    * Removes all key-value entries from the list cache.
 
8904    * @memberOf ListCache
 
8906   function listCacheClear() {
 
8911    * Removes `key` and its value from the list cache.
 
8915    * @memberOf ListCache
 
8916    * @param {string} key The key of the value to remove.
 
8917    * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 
8919   function listCacheDelete(key) {
 
8920     var data = this.__data__,
 
8921         index = assocIndexOf(data, key);
 
8926     var lastIndex = data.length - 1;
 
8927     if (index == lastIndex) {
 
8930       splice.call(data, index, 1);
 
8936    * Gets the list cache value for `key`.
 
8940    * @memberOf ListCache
 
8941    * @param {string} key The key of the value to get.
 
8942    * @returns {*} Returns the entry value.
 
8944   function listCacheGet(key) {
 
8945     var data = this.__data__,
 
8946         index = assocIndexOf(data, key);
 
8948     return index < 0 ? undefined : data[index][1];
 
8952    * Checks if a list cache value for `key` exists.
 
8956    * @memberOf ListCache
 
8957    * @param {string} key The key of the entry to check.
 
8958    * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 
8960   function listCacheHas(key) {
 
8961     return assocIndexOf(this.__data__, key) > -1;
 
8965    * Sets the list cache `key` to `value`.
 
8969    * @memberOf ListCache
 
8970    * @param {string} key The key of the value to set.
 
8971    * @param {*} value The value to set.
 
8972    * @returns {Object} Returns the list cache instance.
 
8974   function listCacheSet(key, value) {
 
8975     var data = this.__data__,
 
8976         index = assocIndexOf(data, key);
 
8979       data.push([key, value]);
 
8981       data[index][1] = value;
 
8986   // Add methods to `ListCache`.
 
8987   ListCache.prototype.clear = listCacheClear;
 
8988   ListCache.prototype['delete'] = listCacheDelete;
 
8989   ListCache.prototype.get = listCacheGet;
 
8990   ListCache.prototype.has = listCacheHas;
 
8991   ListCache.prototype.set = listCacheSet;
 
8993   /*------------------------------------------------------------------------*/
 
8996    * Creates a map cache object to store key-value pairs.
 
9000    * @param {Array} [entries] The key-value pairs to cache.
 
9002   function MapCache(entries) {
 
9004         length = entries ? entries.length : 0;
 
9007     while (++index < length) {
 
9008       var entry = entries[index];
 
9009       this.set(entry[0], entry[1]);
 
9014    * Removes all key-value entries from the map.
 
9018    * @memberOf MapCache
 
9020   function mapCacheClear() {
 
9023       'map': new (Map || ListCache),
 
9029    * Removes `key` and its value from the map.
 
9033    * @memberOf MapCache
 
9034    * @param {string} key The key of the value to remove.
 
9035    * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 
9037   function mapCacheDelete(key) {
 
9038     return getMapData(this, key)['delete'](key);
 
9042    * Gets the map value for `key`.
 
9046    * @memberOf MapCache
 
9047    * @param {string} key The key of the value to get.
 
9048    * @returns {*} Returns the entry value.
 
9050   function mapCacheGet(key) {
 
9051     return getMapData(this, key).get(key);
 
9055    * Checks if a map value for `key` exists.
 
9059    * @memberOf MapCache
 
9060    * @param {string} key The key of the entry to check.
 
9061    * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 
9063   function mapCacheHas(key) {
 
9064     return getMapData(this, key).has(key);
 
9068    * Sets the map `key` to `value`.
 
9072    * @memberOf MapCache
 
9073    * @param {string} key The key of the value to set.
 
9074    * @param {*} value The value to set.
 
9075    * @returns {Object} Returns the map cache instance.
 
9077   function mapCacheSet(key, value) {
 
9078     getMapData(this, key).set(key, value);
 
9082   // Add methods to `MapCache`.
 
9083   MapCache.prototype.clear = mapCacheClear;
 
9084   MapCache.prototype['delete'] = mapCacheDelete;
 
9085   MapCache.prototype.get = mapCacheGet;
 
9086   MapCache.prototype.has = mapCacheHas;
 
9087   MapCache.prototype.set = mapCacheSet;
 
9089   /*------------------------------------------------------------------------*/
 
9093    * Creates an array cache object to store unique values.
 
9097    * @param {Array} [values] The values to cache.
 
9099   function SetCache(values) {
 
9101         length = values ? values.length : 0;
 
9103     this.__data__ = new MapCache;
 
9104     while (++index < length) {
 
9105       this.add(values[index]);
 
9110    * Adds `value` to the array cache.
 
9114    * @memberOf SetCache
 
9116    * @param {*} value The value to cache.
 
9117    * @returns {Object} Returns the cache instance.
 
9119   function setCacheAdd(value) {
 
9120     this.__data__.set(value, HASH_UNDEFINED);
 
9125    * Checks if `value` is in the array cache.
 
9129    * @memberOf SetCache
 
9130    * @param {*} value The value to search for.
 
9131    * @returns {number} Returns `true` if `value` is found, else `false`.
 
9133   function setCacheHas(value) {
 
9134     return this.__data__.has(value);
 
9137   // Add methods to `SetCache`.
 
9138   SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
 
9139   SetCache.prototype.has = setCacheHas;
 
9141   /*------------------------------------------------------------------------*/
 
9144    * Creates a stack cache object to store key-value pairs.
 
9148    * @param {Array} [entries] The key-value pairs to cache.
 
9150   function Stack(entries) {
 
9151     this.__data__ = new ListCache(entries);
 
9155    * Removes all key-value entries from the stack.
 
9161   function stackClear() {
 
9162     this.__data__ = new ListCache;
 
9166    * Removes `key` and its value from the stack.
 
9171    * @param {string} key The key of the value to remove.
 
9172    * @returns {boolean} Returns `true` if the entry was removed, else `false`.
 
9174   function stackDelete(key) {
 
9175     return this.__data__['delete'](key);
 
9179    * Gets the stack value for `key`.
 
9184    * @param {string} key The key of the value to get.
 
9185    * @returns {*} Returns the entry value.
 
9187   function stackGet(key) {
 
9188     return this.__data__.get(key);
 
9192    * Checks if a stack value for `key` exists.
 
9197    * @param {string} key The key of the entry to check.
 
9198    * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
 
9200   function stackHas(key) {
 
9201     return this.__data__.has(key);
 
9205    * Sets the stack `key` to `value`.
 
9210    * @param {string} key The key of the value to set.
 
9211    * @param {*} value The value to set.
 
9212    * @returns {Object} Returns the stack cache instance.
 
9214   function stackSet(key, value) {
 
9215     var cache = this.__data__;
 
9216     if (cache instanceof ListCache && cache.__data__.length == LARGE_ARRAY_SIZE) {
 
9217       cache = this.__data__ = new MapCache(cache.__data__);
 
9219     cache.set(key, value);
 
9223   // Add methods to `Stack`.
 
9224   Stack.prototype.clear = stackClear;
 
9225   Stack.prototype['delete'] = stackDelete;
 
9226   Stack.prototype.get = stackGet;
 
9227   Stack.prototype.has = stackHas;
 
9228   Stack.prototype.set = stackSet;
 
9230   /*------------------------------------------------------------------------*/
 
9233    * This function is like `assignValue` except that it doesn't assign
 
9234    * `undefined` values.
 
9237    * @param {Object} object The object to modify.
 
9238    * @param {string} key The key of the property to assign.
 
9239    * @param {*} value The value to assign.
 
9241   function assignMergeValue(object, key, value) {
 
9242     if ((value !== undefined && !eq(object[key], value)) ||
 
9243         (typeof key == 'number' && value === undefined && !(key in object))) {
 
9244       object[key] = value;
 
9249    * Assigns `value` to `key` of `object` if the existing value is not equivalent
 
9250    * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
 
9251    * for equality comparisons.
 
9254    * @param {Object} object The object to modify.
 
9255    * @param {string} key The key of the property to assign.
 
9256    * @param {*} value The value to assign.
 
9258   function assignValue(object, key, value) {
 
9259     var objValue = object[key];
 
9260     if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
 
9261         (value === undefined && !(key in object))) {
 
9262       object[key] = value;
 
9267    * Gets the index at which the `key` is found in `array` of key-value pairs.
 
9270    * @param {Array} array The array to search.
 
9271    * @param {*} key The key to search for.
 
9272    * @returns {number} Returns the index of the matched value, else `-1`.
 
9274   function assocIndexOf(array, key) {
 
9275     var length = array.length;
 
9277       if (eq(array[length][0], key)) {
 
9285    * Aggregates elements of `collection` on `accumulator` with keys transformed
 
9286    * by `iteratee` and values set by `setter`.
 
9289    * @param {Array|Object} collection The collection to iterate over.
 
9290    * @param {Function} setter The function to set `accumulator` values.
 
9291    * @param {Function} iteratee The iteratee to transform keys.
 
9292    * @param {Object} accumulator The initial aggregated object.
 
9293    * @returns {Function} Returns `accumulator`.
 
9295   function baseAggregator(collection, setter, iteratee, accumulator) {
 
9296     baseEach(collection, function(value, key, collection) {
 
9297       setter(accumulator, value, iteratee(value), collection);
 
9303    * The base implementation of `_.assign` without support for multiple sources
 
9304    * or `customizer` functions.
 
9307    * @param {Object} object The destination object.
 
9308    * @param {Object} source The source object.
 
9309    * @returns {Object} Returns `object`.
 
9311   function baseAssign(object, source) {
 
9312     return object && copyObject(source, keys(source), object);
 
9316    * The base implementation of `_.at` without support for individual paths.
 
9319    * @param {Object} object The object to iterate over.
 
9320    * @param {string[]} paths The property paths of elements to pick.
 
9321    * @returns {Array} Returns the picked elements.
 
9323   function baseAt(object, paths) {
 
9325         isNil = object == null,
 
9326         length = paths.length,
 
9327         result = Array(length);
 
9329     while (++index < length) {
 
9330       result[index] = isNil ? undefined : get(object, paths[index]);
 
9336    * The base implementation of `_.clone` and `_.cloneDeep` which tracks
 
9337    * traversed objects.
 
9340    * @param {*} value The value to clone.
 
9341    * @param {boolean} [isDeep] Specify a deep clone.
 
9342    * @param {boolean} [isFull] Specify a clone including symbols.
 
9343    * @param {Function} [customizer] The function to customize cloning.
 
9344    * @param {string} [key] The key of `value`.
 
9345    * @param {Object} [object] The parent object of `value`.
 
9346    * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
 
9347    * @returns {*} Returns the cloned value.
 
9349   function baseClone(value, isDeep, isFull, customizer, key, object, stack) {
 
9352       result = object ? customizer(value, key, object, stack) : customizer(value);
 
9354     if (result !== undefined) {
 
9357     if (!isObject(value)) {
 
9360     var isArr = isArray(value);
 
9362       result = initCloneArray(value);
 
9364         return copyArray(value, result);
 
9367       var tag = getTag(value),
 
9368           isFunc = tag == funcTag || tag == genTag;
 
9370       if (isBuffer(value)) {
 
9371         return cloneBuffer(value, isDeep);
 
9373       if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
 
9374         if (isHostObject(value)) {
 
9375           return object ? value : {};
 
9377         result = initCloneObject(isFunc ? {} : value);
 
9379           return copySymbols(value, baseAssign(result, value));
 
9382         if (!cloneableTags[tag]) {
 
9383           return object ? value : {};
 
9385         result = initCloneByTag(value, tag, baseClone, isDeep);
 
9388     // Check for circular references and return its corresponding clone.
 
9389     stack || (stack = new Stack);
 
9390     var stacked = stack.get(value);
 
9394     stack.set(value, result);
 
9397       var props = isFull ? getAllKeys(value) : keys(value);
 
9399     // Recursively populate clone (susceptible to call stack limits).
 
9400     arrayEach(props || value, function(subValue, key) {
 
9403         subValue = value[key];
 
9405       assignValue(result, key, baseClone(subValue, isDeep, isFull, customizer, key, value, stack));
 
9411    * The base implementation of `_.create` without support for assigning
 
9412    * properties to the created object.
 
9415    * @param {Object} prototype The object to inherit from.
 
9416    * @returns {Object} Returns the new object.
 
9418   function baseCreate(proto) {
 
9419     return isObject(proto) ? objectCreate(proto) : {};
 
9423    * The base implementation of methods like `_.difference` without support
 
9424    * for excluding multiple arrays or iteratee shorthands.
 
9427    * @param {Array} array The array to inspect.
 
9428    * @param {Array} values The values to exclude.
 
9429    * @param {Function} [iteratee] The iteratee invoked per element.
 
9430    * @param {Function} [comparator] The comparator invoked per element.
 
9431    * @returns {Array} Returns the new array of filtered values.
 
9433   function baseDifference(array, values, iteratee, comparator) {
 
9435         includes = arrayIncludes,
 
9437         length = array.length,
 
9439         valuesLength = values.length;
 
9445       values = arrayMap(values, baseUnary(iteratee));
 
9448       includes = arrayIncludesWith;
 
9451     else if (values.length >= LARGE_ARRAY_SIZE) {
 
9452       includes = cacheHas;
 
9454       values = new SetCache(values);
 
9457     while (++index < length) {
 
9458       var value = array[index],
 
9459           computed = iteratee ? iteratee(value) : value;
 
9461       value = (comparator || value !== 0) ? value : 0;
 
9462       if (isCommon && computed === computed) {
 
9463         var valuesIndex = valuesLength;
 
9464         while (valuesIndex--) {
 
9465           if (values[valuesIndex] === computed) {
 
9471       else if (!includes(values, computed, comparator)) {
 
9479    * The base implementation of `_.forEach` without support for iteratee shorthands.
 
9482    * @param {Array|Object} collection The collection to iterate over.
 
9483    * @param {Function} iteratee The function invoked per iteration.
 
9484    * @returns {Array|Object} Returns `collection`.
 
9486   var baseEach = createBaseEach(baseForOwn);
 
9489    * The base implementation of `_.every` without support for iteratee shorthands.
 
9492    * @param {Array|Object} collection The collection to iterate over.
 
9493    * @param {Function} predicate The function invoked per iteration.
 
9494    * @returns {boolean} Returns `true` if all elements pass the predicate check,
 
9497   function baseEvery(collection, predicate) {
 
9499     baseEach(collection, function(value, index, collection) {
 
9500       result = !!predicate(value, index, collection);
 
9507    * The base implementation of `_.filter` without support for iteratee shorthands.
 
9510    * @param {Array|Object} collection The collection to iterate over.
 
9511    * @param {Function} predicate The function invoked per iteration.
 
9512    * @returns {Array} Returns the new filtered array.
 
9514   function baseFilter(collection, predicate) {
 
9516     baseEach(collection, function(value, index, collection) {
 
9517       if (predicate(value, index, collection)) {
 
9525    * The base implementation of `_.flatten` with support for restricting flattening.
 
9528    * @param {Array} array The array to flatten.
 
9529    * @param {number} depth The maximum recursion depth.
 
9530    * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
 
9531    * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
 
9532    * @param {Array} [result=[]] The initial result value.
 
9533    * @returns {Array} Returns the new flattened array.
 
9535   function baseFlatten(array, depth, predicate, isStrict, result) {
 
9537         length = array.length;
 
9539     predicate || (predicate = isFlattenable);
 
9540     result || (result = []);
 
9542     while (++index < length) {
 
9543       var value = array[index];
 
9544       if (depth > 0 && predicate(value)) {
 
9546           // Recursively flatten arrays (susceptible to call stack limits).
 
9547           baseFlatten(value, depth - 1, predicate, isStrict, result);
 
9549           arrayPush(result, value);
 
9551       } else if (!isStrict) {
 
9552         result[result.length] = value;
 
9559    * The base implementation of `baseForOwn` which iterates over `object`
 
9560    * properties returned by `keysFunc` and invokes `iteratee` for each property.
 
9561    * Iteratee functions may exit iteration early by explicitly returning `false`.
 
9564    * @param {Object} object The object to iterate over.
 
9565    * @param {Function} iteratee The function invoked per iteration.
 
9566    * @param {Function} keysFunc The function to get the keys of `object`.
 
9567    * @returns {Object} Returns `object`.
 
9569   var baseFor = createBaseFor();
 
9572    * The base implementation of `_.forOwn` without support for iteratee shorthands.
 
9575    * @param {Object} object The object to iterate over.
 
9576    * @param {Function} iteratee The function invoked per iteration.
 
9577    * @returns {Object} Returns `object`.
 
9579   function baseForOwn(object, iteratee) {
 
9580     return object && baseFor(object, iteratee, keys);
 
9584    * The base implementation of `_.functions` which creates an array of
 
9585    * `object` function property names filtered from `props`.
 
9588    * @param {Object} object The object to inspect.
 
9589    * @param {Array} props The property names to filter.
 
9590    * @returns {Array} Returns the function names.
 
9592   function baseFunctions(object, props) {
 
9593     return arrayFilter(props, function(key) {
 
9594       return isFunction(object[key]);
 
9599    * The base implementation of `_.get` without support for default values.
 
9602    * @param {Object} object The object to query.
 
9603    * @param {Array|string} path The path of the property to get.
 
9604    * @returns {*} Returns the resolved value.
 
9606   function baseGet(object, path) {
 
9607     path = isKey(path, object) ? [path] : castPath(path);
 
9610         length = path.length;
 
9612     while (object != null && index < length) {
 
9613       object = object[toKey(path[index++])];
 
9615     return (index && index == length) ? object : undefined;
 
9619    * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
 
9620    * `keysFunc` and `symbolsFunc` to get the enumerable property names and
 
9621    * symbols of `object`.
 
9624    * @param {Object} object The object to query.
 
9625    * @param {Function} keysFunc The function to get the keys of `object`.
 
9626    * @param {Function} symbolsFunc The function to get the symbols of `object`.
 
9627    * @returns {Array} Returns the array of property names and symbols.
 
9629   function baseGetAllKeys(object, keysFunc, symbolsFunc) {
 
9630     var result = keysFunc(object);
 
9631     return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
 
9635    * The base implementation of `_.has` without support for deep paths.
 
9638    * @param {Object} object The object to query.
 
9639    * @param {Array|string} key The key to check.
 
9640    * @returns {boolean} Returns `true` if `key` exists, else `false`.
 
9642   function baseHas(object, key) {
 
9643     // Avoid a bug in IE 10-11 where objects with a [[Prototype]] of `null`,
 
9644     // that are composed entirely of index properties, return `false` for
 
9645     // `hasOwnProperty` checks of them.
 
9646     return hasOwnProperty.call(object, key) ||
 
9647       (typeof object == 'object' && key in object && getPrototype(object) === null);
 
9651    * The base implementation of `_.hasIn` without support for deep paths.
 
9654    * @param {Object} object The object to query.
 
9655    * @param {Array|string} key The key to check.
 
9656    * @returns {boolean} Returns `true` if `key` exists, else `false`.
 
9658   function baseHasIn(object, key) {
 
9659     return key in Object(object);
 
9663    * The base implementation of methods like `_.intersection`, without support
 
9664    * for iteratee shorthands, that accepts an array of arrays to inspect.
 
9667    * @param {Array} arrays The arrays to inspect.
 
9668    * @param {Function} [iteratee] The iteratee invoked per element.
 
9669    * @param {Function} [comparator] The comparator invoked per element.
 
9670    * @returns {Array} Returns the new array of shared values.
 
9672   function baseIntersection(arrays, iteratee, comparator) {
 
9673     var includes = comparator ? arrayIncludesWith : arrayIncludes,
 
9674         length = arrays[0].length,
 
9675         othLength = arrays.length,
 
9676         othIndex = othLength,
 
9677         caches = Array(othLength),
 
9678         maxLength = Infinity,
 
9681     while (othIndex--) {
 
9682       var array = arrays[othIndex];
 
9683       if (othIndex && iteratee) {
 
9684         array = arrayMap(array, baseUnary(iteratee));
 
9686       maxLength = nativeMin(array.length, maxLength);
 
9687       caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120))
 
9688         ? new SetCache(othIndex && array)
 
9697     while (++index < length && result.length < maxLength) {
 
9698       var value = array[index],
 
9699           computed = iteratee ? iteratee(value) : value;
 
9701       value = (comparator || value !== 0) ? value : 0;
 
9703             ? cacheHas(seen, computed)
 
9704             : includes(result, computed, comparator)
 
9706         othIndex = othLength;
 
9707         while (--othIndex) {
 
9708           var cache = caches[othIndex];
 
9710                 ? cacheHas(cache, computed)
 
9711                 : includes(arrays[othIndex], computed, comparator))
 
9717           seen.push(computed);
 
9726    * The base implementation of `_.invoke` without support for individual
 
9730    * @param {Object} object The object to query.
 
9731    * @param {Array|string} path The path of the method to invoke.
 
9732    * @param {Array} args The arguments to invoke the method with.
 
9733    * @returns {*} Returns the result of the invoked method.
 
9735   function baseInvoke(object, path, args) {
 
9736     if (!isKey(path, object)) {
 
9737       path = castPath(path);
 
9738       object = parent(object, path);
 
9741     var func = object == null ? object : object[toKey(path)];
 
9742     return func == null ? undefined : apply(func, object, args);
 
9746    * The base implementation of `_.isEqual` which supports partial comparisons
 
9747    * and tracks traversed objects.
 
9750    * @param {*} value The value to compare.
 
9751    * @param {*} other The other value to compare.
 
9752    * @param {Function} [customizer] The function to customize comparisons.
 
9753    * @param {boolean} [bitmask] The bitmask of comparison flags.
 
9754    *  The bitmask may be composed of the following flags:
 
9755    *     1 - Unordered comparison
 
9756    *     2 - Partial comparison
 
9757    * @param {Object} [stack] Tracks traversed `value` and `other` objects.
 
9758    * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 
9760   function baseIsEqual(value, other, customizer, bitmask, stack) {
 
9761     if (value === other) {
 
9764     if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {
 
9765       return value !== value && other !== other;
 
9767     return baseIsEqualDeep(value, other, baseIsEqual, customizer, bitmask, stack);
 
9771    * A specialized version of `baseIsEqual` for arrays and objects which performs
 
9772    * deep comparisons and tracks traversed objects enabling objects with circular
 
9773    * references to be compared.
 
9776    * @param {Object} object The object to compare.
 
9777    * @param {Object} other The other object to compare.
 
9778    * @param {Function} equalFunc The function to determine equivalents of values.
 
9779    * @param {Function} [customizer] The function to customize comparisons.
 
9780    * @param {number} [bitmask] The bitmask of comparison flags. See `baseIsEqual`
 
9782    * @param {Object} [stack] Tracks traversed `object` and `other` objects.
 
9783    * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 
9785   function baseIsEqualDeep(object, other, equalFunc, customizer, bitmask, stack) {
 
9786     var objIsArr = isArray(object),
 
9787         othIsArr = isArray(other),
 
9792       objTag = getTag(object);
 
9793       objTag = objTag == argsTag ? objectTag : objTag;
 
9796       othTag = getTag(other);
 
9797       othTag = othTag == argsTag ? objectTag : othTag;
 
9799     var objIsObj = objTag == objectTag && !isHostObject(object),
 
9800         othIsObj = othTag == objectTag && !isHostObject(other),
 
9801         isSameTag = objTag == othTag;
 
9803     if (isSameTag && !objIsObj) {
 
9804       stack || (stack = new Stack);
 
9805       return (objIsArr || isTypedArray(object))
 
9806         ? equalArrays(object, other, equalFunc, customizer, bitmask, stack)
 
9807         : equalByTag(object, other, objTag, equalFunc, customizer, bitmask, stack);
 
9809     if (!(bitmask & PARTIAL_COMPARE_FLAG)) {
 
9810       var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
 
9811           othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
 
9813       if (objIsWrapped || othIsWrapped) {
 
9814         var objUnwrapped = objIsWrapped ? object.value() : object,
 
9815             othUnwrapped = othIsWrapped ? other.value() : other;
 
9817         stack || (stack = new Stack);
 
9818         return equalFunc(objUnwrapped, othUnwrapped, customizer, bitmask, stack);
 
9824     stack || (stack = new Stack);
 
9825     return equalObjects(object, other, equalFunc, customizer, bitmask, stack);
 
9829    * The base implementation of `_.isMatch` without support for iteratee shorthands.
 
9832    * @param {Object} object The object to inspect.
 
9833    * @param {Object} source The object of property values to match.
 
9834    * @param {Array} matchData The property names, values, and compare flags to match.
 
9835    * @param {Function} [customizer] The function to customize comparisons.
 
9836    * @returns {boolean} Returns `true` if `object` is a match, else `false`.
 
9838   function baseIsMatch(object, source, matchData, customizer) {
 
9839     var index = matchData.length,
 
9841         noCustomizer = !customizer;
 
9843     if (object == null) {
 
9846     object = Object(object);
 
9848       var data = matchData[index];
 
9849       if ((noCustomizer && data[2])
 
9850             ? data[1] !== object[data[0]]
 
9851             : !(data[0] in object)
 
9856     while (++index < length) {
 
9857       data = matchData[index];
 
9859           objValue = object[key],
 
9862       if (noCustomizer && data[2]) {
 
9863         if (objValue === undefined && !(key in object)) {
 
9867         var stack = new Stack;
 
9869           var result = customizer(objValue, srcValue, key, object, source, stack);
 
9871         if (!(result === undefined
 
9872               ? baseIsEqual(srcValue, objValue, customizer, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG, stack)
 
9883    * The base implementation of `_.iteratee`.
 
9886    * @param {*} [value=_.identity] The value to convert to an iteratee.
 
9887    * @returns {Function} Returns the iteratee.
 
9889   function baseIteratee(value) {
 
9890     // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
 
9891     // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
 
9892     if (typeof value == 'function') {
 
9895     if (value == null) {
 
9898     if (typeof value == 'object') {
 
9899       return isArray(value)
 
9900         ? baseMatchesProperty(value[0], value[1])
 
9901         : baseMatches(value);
 
9903     return property(value);
 
9907    * The base implementation of `_.keys` which doesn't skip the constructor
 
9908    * property of prototypes or treat sparse arrays as dense.
 
9911    * @param {Object} object The object to query.
 
9912    * @returns {Array} Returns the array of property names.
 
9914   function baseKeys(object) {
 
9915     return nativeKeys(Object(object));
 
9919    * The base implementation of `_.keysIn` which doesn't skip the constructor
 
9920    * property of prototypes or treat sparse arrays as dense.
 
9923    * @param {Object} object The object to query.
 
9924    * @returns {Array} Returns the array of property names.
 
9926   function baseKeysIn(object) {
 
9927     object = object == null ? object : Object(object);
 
9930     for (var key in object) {
 
9936   // Fallback for IE < 9 with es6-shim.
 
9937   if (enumerate && !propertyIsEnumerable.call({ 'valueOf': 1 }, 'valueOf')) {
 
9938     baseKeysIn = function(object) {
 
9939       return iteratorToArray(enumerate(object));
 
9944    * The base implementation of `_.map` without support for iteratee shorthands.
 
9947    * @param {Array|Object} collection The collection to iterate over.
 
9948    * @param {Function} iteratee The function invoked per iteration.
 
9949    * @returns {Array} Returns the new mapped array.
 
9951   function baseMap(collection, iteratee) {
 
9953         result = isArrayLike(collection) ? Array(collection.length) : [];
 
9955     baseEach(collection, function(value, key, collection) {
 
9956       result[++index] = iteratee(value, key, collection);
 
9962    * The base implementation of `_.matches` which doesn't clone `source`.
 
9965    * @param {Object} source The object of property values to match.
 
9966    * @returns {Function} Returns the new spec function.
 
9968   function baseMatches(source) {
 
9969     var matchData = getMatchData(source);
 
9970     if (matchData.length == 1 && matchData[0][2]) {
 
9971       return matchesStrictComparable(matchData[0][0], matchData[0][1]);
 
9973     return function(object) {
 
9974       return object === source || baseIsMatch(object, source, matchData);
 
9979    * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
 
9982    * @param {string} path The path of the property to get.
 
9983    * @param {*} srcValue The value to match.
 
9984    * @returns {Function} Returns the new spec function.
 
9986   function baseMatchesProperty(path, srcValue) {
 
9987     if (isKey(path) && isStrictComparable(srcValue)) {
 
9988       return matchesStrictComparable(toKey(path), srcValue);
 
9990     return function(object) {
 
9991       var objValue = get(object, path);
 
9992       return (objValue === undefined && objValue === srcValue)
 
9993         ? hasIn(object, path)
 
9994         : baseIsEqual(srcValue, objValue, undefined, UNORDERED_COMPARE_FLAG | PARTIAL_COMPARE_FLAG);
 
9999    * The base implementation of `_.merge` without support for multiple sources.
 
10002    * @param {Object} object The destination object.
 
10003    * @param {Object} source The source object.
 
10004    * @param {number} srcIndex The index of `source`.
 
10005    * @param {Function} [customizer] The function to customize merged values.
 
10006    * @param {Object} [stack] Tracks traversed source values and their merged
 
10009   function baseMerge(object, source, srcIndex, customizer, stack) {
 
10010     if (object === source) {
 
10013     if (!(isArray(source) || isTypedArray(source))) {
 
10014       var props = keysIn(source);
 
10016     arrayEach(props || source, function(srcValue, key) {
 
10019         srcValue = source[key];
 
10021       if (isObject(srcValue)) {
 
10022         stack || (stack = new Stack);
 
10023         baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
 
10026         var newValue = customizer
 
10027           ? customizer(object[key], srcValue, (key + ''), object, source, stack)
 
10030         if (newValue === undefined) {
 
10031           newValue = srcValue;
 
10033         assignMergeValue(object, key, newValue);
 
10039    * A specialized version of `baseMerge` for arrays and objects which performs
 
10040    * deep merges and tracks traversed objects enabling objects with circular
 
10041    * references to be merged.
 
10044    * @param {Object} object The destination object.
 
10045    * @param {Object} source The source object.
 
10046    * @param {string} key The key of the value to merge.
 
10047    * @param {number} srcIndex The index of `source`.
 
10048    * @param {Function} mergeFunc The function to merge values.
 
10049    * @param {Function} [customizer] The function to customize assigned values.
 
10050    * @param {Object} [stack] Tracks traversed source values and their merged
 
10053   function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
 
10054     var objValue = object[key],
 
10055         srcValue = source[key],
 
10056         stacked = stack.get(srcValue);
 
10059       assignMergeValue(object, key, stacked);
 
10062     var newValue = customizer
 
10063       ? customizer(objValue, srcValue, (key + ''), object, source, stack)
 
10066     var isCommon = newValue === undefined;
 
10069       newValue = srcValue;
 
10070       if (isArray(srcValue) || isTypedArray(srcValue)) {
 
10071         if (isArray(objValue)) {
 
10072           newValue = objValue;
 
10074         else if (isArrayLikeObject(objValue)) {
 
10075           newValue = copyArray(objValue);
 
10079           newValue = baseClone(srcValue, true);
 
10082       else if (isPlainObject(srcValue) || isArguments(srcValue)) {
 
10083         if (isArguments(objValue)) {
 
10084           newValue = toPlainObject(objValue);
 
10086         else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) {
 
10088           newValue = baseClone(srcValue, true);
 
10091           newValue = objValue;
 
10098     stack.set(srcValue, newValue);
 
10101       // Recursively merge objects and arrays (susceptible to call stack limits).
 
10102       mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
 
10104     stack['delete'](srcValue);
 
10105     assignMergeValue(object, key, newValue);
 
10109    * The base implementation of `_.pick` without support for individual
 
10110    * property identifiers.
 
10113    * @param {Object} object The source object.
 
10114    * @param {string[]} props The property identifiers to pick.
 
10115    * @returns {Object} Returns the new object.
 
10117   function basePick(object, props) {
 
10118     object = Object(object);
 
10119     return arrayReduce(props, function(result, key) {
 
10120       if (key in object) {
 
10121         result[key] = object[key];
 
10128    * The base implementation of `_.property` without support for deep paths.
 
10131    * @param {string} key The key of the property to get.
 
10132    * @returns {Function} Returns the new accessor function.
 
10134   function baseProperty(key) {
 
10135     return function(object) {
 
10136       return object == null ? undefined : object[key];
 
10141    * A specialized version of `baseProperty` which supports deep paths.
 
10144    * @param {Array|string} path The path of the property to get.
 
10145    * @returns {Function} Returns the new accessor function.
 
10147   function basePropertyDeep(path) {
 
10148     return function(object) {
 
10149       return baseGet(object, path);
 
10154    * The base implementation of `setData` without support for hot loop detection.
 
10157    * @param {Function} func The function to associate metadata with.
 
10158    * @param {*} data The metadata.
 
10159    * @returns {Function} Returns `func`.
 
10161   var baseSetData = !metaMap ? identity : function(func, data) {
 
10162     metaMap.set(func, data);
 
10167    * The base implementation of `_.slice` without an iteratee call guard.
 
10170    * @param {Array} array The array to slice.
 
10171    * @param {number} [start=0] The start position.
 
10172    * @param {number} [end=array.length] The end position.
 
10173    * @returns {Array} Returns the slice of `array`.
 
10175   function baseSlice(array, start, end) {
 
10177         length = array.length;
 
10180       start = -start > length ? 0 : (length + start);
 
10182     end = end > length ? length : end;
 
10186     length = start > end ? 0 : ((end - start) >>> 0);
 
10189     var result = Array(length);
 
10190     while (++index < length) {
 
10191       result[index] = array[index + start];
 
10197    * The base implementation of `_.some` without support for iteratee shorthands.
 
10200    * @param {Array|Object} collection The collection to iterate over.
 
10201    * @param {Function} predicate The function invoked per iteration.
 
10202    * @returns {boolean} Returns `true` if any element passes the predicate check,
 
10205   function baseSome(collection, predicate) {
 
10208     baseEach(collection, function(value, index, collection) {
 
10209       result = predicate(value, index, collection);
 
10216    * The base implementation of `_.toString` which doesn't convert nullish
 
10217    * values to empty strings.
 
10220    * @param {*} value The value to process.
 
10221    * @returns {string} Returns the string.
 
10223   function baseToString(value) {
 
10224     // Exit early for strings to avoid a performance hit in some environments.
 
10225     if (typeof value == 'string') {
 
10228     if (isSymbol(value)) {
 
10229       return symbolToString ? symbolToString.call(value) : '';
 
10231     var result = (value + '');
 
10232     return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
 
10236    * The base implementation of `_.uniqBy` without support for iteratee shorthands.
 
10239    * @param {Array} array The array to inspect.
 
10240    * @param {Function} [iteratee] The iteratee invoked per element.
 
10241    * @param {Function} [comparator] The comparator invoked per element.
 
10242    * @returns {Array} Returns the new duplicate free array.
 
10244   function baseUniq(array, iteratee, comparator) {
 
10246         includes = arrayIncludes,
 
10247         length = array.length,
 
10254       includes = arrayIncludesWith;
 
10256     else if (length >= LARGE_ARRAY_SIZE) {
 
10257       var set = iteratee ? null : createSet(array);
 
10259         return setToArray(set);
 
10262       includes = cacheHas;
 
10263       seen = new SetCache;
 
10266       seen = iteratee ? [] : result;
 
10269     while (++index < length) {
 
10270       var value = array[index],
 
10271           computed = iteratee ? iteratee(value) : value;
 
10273       value = (comparator || value !== 0) ? value : 0;
 
10274       if (isCommon && computed === computed) {
 
10275         var seenIndex = seen.length;
 
10276         while (seenIndex--) {
 
10277           if (seen[seenIndex] === computed) {
 
10282           seen.push(computed);
 
10284         result.push(value);
 
10286       else if (!includes(seen, computed, comparator)) {
 
10287         if (seen !== result) {
 
10288           seen.push(computed);
 
10290         result.push(value);
 
10297    * The base implementation of `wrapperValue` which returns the result of
 
10298    * performing a sequence of actions on the unwrapped `value`, where each
 
10299    * successive action is supplied the return value of the previous.
 
10302    * @param {*} value The unwrapped value.
 
10303    * @param {Array} actions Actions to perform to resolve the unwrapped value.
 
10304    * @returns {*} Returns the resolved value.
 
10306   function baseWrapperValue(value, actions) {
 
10307     var result = value;
 
10308     if (result instanceof LazyWrapper) {
 
10309       result = result.value();
 
10311     return arrayReduce(actions, function(result, action) {
 
10312       return action.func.apply(action.thisArg, arrayPush([result], action.args));
 
10317    * Casts `value` to an empty array if it's not an array like object.
 
10320    * @param {*} value The value to inspect.
 
10321    * @returns {Array|Object} Returns the cast array-like object.
 
10323   function castArrayLikeObject(value) {
 
10324     return isArrayLikeObject(value) ? value : [];
 
10328    * Casts `value` to a path array if it's not one.
 
10331    * @param {*} value The value to inspect.
 
10332    * @returns {Array} Returns the cast property path array.
 
10334   function castPath(value) {
 
10335     return isArray(value) ? value : stringToPath(value);
 
10339    * Creates a clone of  `buffer`.
 
10342    * @param {Buffer} buffer The buffer to clone.
 
10343    * @param {boolean} [isDeep] Specify a deep clone.
 
10344    * @returns {Buffer} Returns the cloned buffer.
 
10346   function cloneBuffer(buffer, isDeep) {
 
10348       return buffer.slice();
 
10350     var result = new buffer.constructor(buffer.length);
 
10351     buffer.copy(result);
 
10356    * Creates a clone of `arrayBuffer`.
 
10359    * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
 
10360    * @returns {ArrayBuffer} Returns the cloned array buffer.
 
10362   function cloneArrayBuffer(arrayBuffer) {
 
10363     var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
 
10364     new Uint8Array(result).set(new Uint8Array(arrayBuffer));
 
10369    * Creates a clone of `dataView`.
 
10372    * @param {Object} dataView The data view to clone.
 
10373    * @param {boolean} [isDeep] Specify a deep clone.
 
10374    * @returns {Object} Returns the cloned data view.
 
10376   function cloneDataView(dataView, isDeep) {
 
10377     var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
 
10378     return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
 
10382    * Creates a clone of `map`.
 
10385    * @param {Object} map The map to clone.
 
10386    * @param {Function} cloneFunc The function to clone values.
 
10387    * @param {boolean} [isDeep] Specify a deep clone.
 
10388    * @returns {Object} Returns the cloned map.
 
10390   function cloneMap(map, isDeep, cloneFunc) {
 
10391     var array = isDeep ? cloneFunc(mapToArray(map), true) : mapToArray(map);
 
10392     return arrayReduce(array, addMapEntry, new map.constructor);
 
10396    * Creates a clone of `regexp`.
 
10399    * @param {Object} regexp The regexp to clone.
 
10400    * @returns {Object} Returns the cloned regexp.
 
10402   function cloneRegExp(regexp) {
 
10403     var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
 
10404     result.lastIndex = regexp.lastIndex;
 
10409    * Creates a clone of `set`.
 
10412    * @param {Object} set The set to clone.
 
10413    * @param {Function} cloneFunc The function to clone values.
 
10414    * @param {boolean} [isDeep] Specify a deep clone.
 
10415    * @returns {Object} Returns the cloned set.
 
10417   function cloneSet(set, isDeep, cloneFunc) {
 
10418     var array = isDeep ? cloneFunc(setToArray(set), true) : setToArray(set);
 
10419     return arrayReduce(array, addSetEntry, new set.constructor);
 
10423    * Creates a clone of the `symbol` object.
 
10426    * @param {Object} symbol The symbol object to clone.
 
10427    * @returns {Object} Returns the cloned symbol object.
 
10429   function cloneSymbol(symbol) {
 
10430     return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
 
10434    * Creates a clone of `typedArray`.
 
10437    * @param {Object} typedArray The typed array to clone.
 
10438    * @param {boolean} [isDeep] Specify a deep clone.
 
10439    * @returns {Object} Returns the cloned typed array.
 
10441   function cloneTypedArray(typedArray, isDeep) {
 
10442     var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
 
10443     return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
 
10447    * Creates an array that is the composition of partially applied arguments,
 
10448    * placeholders, and provided arguments into a single array of arguments.
 
10451    * @param {Array} args The provided arguments.
 
10452    * @param {Array} partials The arguments to prepend to those provided.
 
10453    * @param {Array} holders The `partials` placeholder indexes.
 
10454    * @params {boolean} [isCurried] Specify composing for a curried function.
 
10455    * @returns {Array} Returns the new array of composed arguments.
 
10457   function composeArgs(args, partials, holders, isCurried) {
 
10458     var argsIndex = -1,
 
10459         argsLength = args.length,
 
10460         holdersLength = holders.length,
 
10462         leftLength = partials.length,
 
10463         rangeLength = nativeMax(argsLength - holdersLength, 0),
 
10464         result = Array(leftLength + rangeLength),
 
10465         isUncurried = !isCurried;
 
10467     while (++leftIndex < leftLength) {
 
10468       result[leftIndex] = partials[leftIndex];
 
10470     while (++argsIndex < holdersLength) {
 
10471       if (isUncurried || argsIndex < argsLength) {
 
10472         result[holders[argsIndex]] = args[argsIndex];
 
10475     while (rangeLength--) {
 
10476       result[leftIndex++] = args[argsIndex++];
 
10482    * This function is like `composeArgs` except that the arguments composition
 
10483    * is tailored for `_.partialRight`.
 
10486    * @param {Array} args The provided arguments.
 
10487    * @param {Array} partials The arguments to append to those provided.
 
10488    * @param {Array} holders The `partials` placeholder indexes.
 
10489    * @params {boolean} [isCurried] Specify composing for a curried function.
 
10490    * @returns {Array} Returns the new array of composed arguments.
 
10492   function composeArgsRight(args, partials, holders, isCurried) {
 
10493     var argsIndex = -1,
 
10494         argsLength = args.length,
 
10496         holdersLength = holders.length,
 
10498         rightLength = partials.length,
 
10499         rangeLength = nativeMax(argsLength - holdersLength, 0),
 
10500         result = Array(rangeLength + rightLength),
 
10501         isUncurried = !isCurried;
 
10503     while (++argsIndex < rangeLength) {
 
10504       result[argsIndex] = args[argsIndex];
 
10506     var offset = argsIndex;
 
10507     while (++rightIndex < rightLength) {
 
10508       result[offset + rightIndex] = partials[rightIndex];
 
10510     while (++holdersIndex < holdersLength) {
 
10511       if (isUncurried || argsIndex < argsLength) {
 
10512         result[offset + holders[holdersIndex]] = args[argsIndex++];
 
10519    * Copies the values of `source` to `array`.
 
10522    * @param {Array} source The array to copy values from.
 
10523    * @param {Array} [array=[]] The array to copy values to.
 
10524    * @returns {Array} Returns `array`.
 
10526   function copyArray(source, array) {
 
10528         length = source.length;
 
10530     array || (array = Array(length));
 
10531     while (++index < length) {
 
10532       array[index] = source[index];
 
10538    * Copies properties of `source` to `object`.
 
10541    * @param {Object} source The object to copy properties from.
 
10542    * @param {Array} props The property identifiers to copy.
 
10543    * @param {Object} [object={}] The object to copy properties to.
 
10544    * @param {Function} [customizer] The function to customize copied values.
 
10545    * @returns {Object} Returns `object`.
 
10547   function copyObject(source, props, object, customizer) {
 
10548     object || (object = {});
 
10551         length = props.length;
 
10553     while (++index < length) {
 
10554       var key = props[index];
 
10556       var newValue = customizer
 
10557         ? customizer(object[key], source[key], key, object, source)
 
10560       assignValue(object, key, newValue);
 
10566    * Copies own symbol properties of `source` to `object`.
 
10569    * @param {Object} source The object to copy symbols from.
 
10570    * @param {Object} [object={}] The object to copy symbols to.
 
10571    * @returns {Object} Returns `object`.
 
10573   function copySymbols(source, object) {
 
10574     return copyObject(source, getSymbols(source), object);
 
10578    * Creates a function like `_.groupBy`.
 
10581    * @param {Function} setter The function to set accumulator values.
 
10582    * @param {Function} [initializer] The accumulator object initializer.
 
10583    * @returns {Function} Returns the new aggregator function.
 
10585   function createAggregator(setter, initializer) {
 
10586     return function(collection, iteratee) {
 
10587       var func = isArray(collection) ? arrayAggregator : baseAggregator,
 
10588           accumulator = initializer ? initializer() : {};
 
10590       return func(collection, setter, getIteratee(iteratee), accumulator);
 
10595    * Creates a function like `_.assign`.
 
10598    * @param {Function} assigner The function to assign values.
 
10599    * @returns {Function} Returns the new assigner function.
 
10601   function createAssigner(assigner) {
 
10602     return rest(function(object, sources) {
 
10604           length = sources.length,
 
10605           customizer = length > 1 ? sources[length - 1] : undefined,
 
10606           guard = length > 2 ? sources[2] : undefined;
 
10608       customizer = (assigner.length > 3 && typeof customizer == 'function')
 
10609         ? (length--, customizer)
 
10612       if (guard && isIterateeCall(sources[0], sources[1], guard)) {
 
10613         customizer = length < 3 ? undefined : customizer;
 
10616       object = Object(object);
 
10617       while (++index < length) {
 
10618         var source = sources[index];
 
10620           assigner(object, source, index, customizer);
 
10628    * Creates a `baseEach` or `baseEachRight` function.
 
10631    * @param {Function} eachFunc The function to iterate over a collection.
 
10632    * @param {boolean} [fromRight] Specify iterating from right to left.
 
10633    * @returns {Function} Returns the new base function.
 
10635   function createBaseEach(eachFunc, fromRight) {
 
10636     return function(collection, iteratee) {
 
10637       if (collection == null) {
 
10640       if (!isArrayLike(collection)) {
 
10641         return eachFunc(collection, iteratee);
 
10643       var length = collection.length,
 
10644           index = fromRight ? length : -1,
 
10645           iterable = Object(collection);
 
10647       while ((fromRight ? index-- : ++index < length)) {
 
10648         if (iteratee(iterable[index], index, iterable) === false) {
 
10657    * Creates a base function for methods like `_.forIn` and `_.forOwn`.
 
10660    * @param {boolean} [fromRight] Specify iterating from right to left.
 
10661    * @returns {Function} Returns the new base function.
 
10663   function createBaseFor(fromRight) {
 
10664     return function(object, iteratee, keysFunc) {
 
10666           iterable = Object(object),
 
10667           props = keysFunc(object),
 
10668           length = props.length;
 
10671         var key = props[fromRight ? length : ++index];
 
10672         if (iteratee(iterable[key], key, iterable) === false) {
 
10681    * Creates a function that wraps `func` to invoke it with the optional `this`
 
10682    * binding of `thisArg`.
 
10685    * @param {Function} func The function to wrap.
 
10686    * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper`
 
10687    *  for more details.
 
10688    * @param {*} [thisArg] The `this` binding of `func`.
 
10689    * @returns {Function} Returns the new wrapped function.
 
10691   function createBaseWrapper(func, bitmask, thisArg) {
 
10692     var isBind = bitmask & BIND_FLAG,
 
10693         Ctor = createCtorWrapper(func);
 
10695     function wrapper() {
 
10696       var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
 
10697       return fn.apply(isBind ? thisArg : this, arguments);
 
10703    * Creates a function that produces an instance of `Ctor` regardless of
 
10704    * whether it was invoked as part of a `new` expression or by `call` or `apply`.
 
10707    * @param {Function} Ctor The constructor to wrap.
 
10708    * @returns {Function} Returns the new wrapped function.
 
10710   function createCtorWrapper(Ctor) {
 
10711     return function() {
 
10712       // Use a `switch` statement to work with class constructors. See
 
10713       // http://ecma-international.org/ecma-262/6.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
 
10714       // for more details.
 
10715       var args = arguments;
 
10716       switch (args.length) {
 
10717         case 0: return new Ctor;
 
10718         case 1: return new Ctor(args[0]);
 
10719         case 2: return new Ctor(args[0], args[1]);
 
10720         case 3: return new Ctor(args[0], args[1], args[2]);
 
10721         case 4: return new Ctor(args[0], args[1], args[2], args[3]);
 
10722         case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);
 
10723         case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
 
10724         case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
 
10726       var thisBinding = baseCreate(Ctor.prototype),
 
10727           result = Ctor.apply(thisBinding, args);
 
10729       // Mimic the constructor's `return` behavior.
 
10730       // See https://es5.github.io/#x13.2.2 for more details.
 
10731       return isObject(result) ? result : thisBinding;
 
10736    * Creates a function that wraps `func` to enable currying.
 
10739    * @param {Function} func The function to wrap.
 
10740    * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper`
 
10741    *  for more details.
 
10742    * @param {number} arity The arity of `func`.
 
10743    * @returns {Function} Returns the new wrapped function.
 
10745   function createCurryWrapper(func, bitmask, arity) {
 
10746     var Ctor = createCtorWrapper(func);
 
10748     function wrapper() {
 
10749       var length = arguments.length,
 
10750           args = Array(length),
 
10752           placeholder = getHolder(wrapper);
 
10755         args[index] = arguments[index];
 
10757       var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder)
 
10759         : replaceHolders(args, placeholder);
 
10761       length -= holders.length;
 
10762       if (length < arity) {
 
10763         return createRecurryWrapper(
 
10764           func, bitmask, createHybridWrapper, wrapper.placeholder, undefined,
 
10765           args, holders, undefined, undefined, arity - length);
 
10767       var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
 
10768       return apply(fn, this, args);
 
10774    * Creates a function that wraps `func` to invoke it with optional `this`
 
10775    * binding of `thisArg`, partial application, and currying.
 
10778    * @param {Function|string} func The function or method name to wrap.
 
10779    * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper`
 
10780    *  for more details.
 
10781    * @param {*} [thisArg] The `this` binding of `func`.
 
10782    * @param {Array} [partials] The arguments to prepend to those provided to
 
10783    *  the new function.
 
10784    * @param {Array} [holders] The `partials` placeholder indexes.
 
10785    * @param {Array} [partialsRight] The arguments to append to those provided
 
10786    *  to the new function.
 
10787    * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
 
10788    * @param {Array} [argPos] The argument positions of the new function.
 
10789    * @param {number} [ary] The arity cap of `func`.
 
10790    * @param {number} [arity] The arity of `func`.
 
10791    * @returns {Function} Returns the new wrapped function.
 
10793   function createHybridWrapper(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
 
10794     var isAry = bitmask & ARY_FLAG,
 
10795         isBind = bitmask & BIND_FLAG,
 
10796         isBindKey = bitmask & BIND_KEY_FLAG,
 
10797         isCurried = bitmask & (CURRY_FLAG | CURRY_RIGHT_FLAG),
 
10798         isFlip = bitmask & FLIP_FLAG,
 
10799         Ctor = isBindKey ? undefined : createCtorWrapper(func);
 
10801     function wrapper() {
 
10802       var length = arguments.length,
 
10803           args = Array(length),
 
10807         args[index] = arguments[index];
 
10810         var placeholder = getHolder(wrapper),
 
10811             holdersCount = countHolders(args, placeholder);
 
10814         args = composeArgs(args, partials, holders, isCurried);
 
10816       if (partialsRight) {
 
10817         args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
 
10819       length -= holdersCount;
 
10820       if (isCurried && length < arity) {
 
10821         var newHolders = replaceHolders(args, placeholder);
 
10822         return createRecurryWrapper(
 
10823           func, bitmask, createHybridWrapper, wrapper.placeholder, thisArg,
 
10824           args, newHolders, argPos, ary, arity - length
 
10827       var thisBinding = isBind ? thisArg : this,
 
10828           fn = isBindKey ? thisBinding[func] : func;
 
10830       length = args.length;
 
10832         args = reorder(args, argPos);
 
10833       } else if (isFlip && length > 1) {
 
10836       if (isAry && ary < length) {
 
10839       if (this && this !== root && this instanceof wrapper) {
 
10840         fn = Ctor || createCtorWrapper(fn);
 
10842       return fn.apply(thisBinding, args);
 
10848    * Creates a function that wraps `func` to invoke it with the `this` binding
 
10849    * of `thisArg` and `partials` prepended to the arguments it receives.
 
10852    * @param {Function} func The function to wrap.
 
10853    * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper`
 
10854    *  for more details.
 
10855    * @param {*} thisArg The `this` binding of `func`.
 
10856    * @param {Array} partials The arguments to prepend to those provided to
 
10857    *  the new function.
 
10858    * @returns {Function} Returns the new wrapped function.
 
10860   function createPartialWrapper(func, bitmask, thisArg, partials) {
 
10861     var isBind = bitmask & BIND_FLAG,
 
10862         Ctor = createCtorWrapper(func);
 
10864     function wrapper() {
 
10865       var argsIndex = -1,
 
10866           argsLength = arguments.length,
 
10868           leftLength = partials.length,
 
10869           args = Array(leftLength + argsLength),
 
10870           fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
 
10872       while (++leftIndex < leftLength) {
 
10873         args[leftIndex] = partials[leftIndex];
 
10875       while (argsLength--) {
 
10876         args[leftIndex++] = arguments[++argsIndex];
 
10878       return apply(fn, isBind ? thisArg : this, args);
 
10884    * Creates a function that wraps `func` to continue currying.
 
10887    * @param {Function} func The function to wrap.
 
10888    * @param {number} bitmask The bitmask of wrapper flags. See `createWrapper`
 
10889    *  for more details.
 
10890    * @param {Function} wrapFunc The function to create the `func` wrapper.
 
10891    * @param {*} placeholder The placeholder value.
 
10892    * @param {*} [thisArg] The `this` binding of `func`.
 
10893    * @param {Array} [partials] The arguments to prepend to those provided to
 
10894    *  the new function.
 
10895    * @param {Array} [holders] The `partials` placeholder indexes.
 
10896    * @param {Array} [argPos] The argument positions of the new function.
 
10897    * @param {number} [ary] The arity cap of `func`.
 
10898    * @param {number} [arity] The arity of `func`.
 
10899    * @returns {Function} Returns the new wrapped function.
 
10901   function createRecurryWrapper(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
 
10902     var isCurry = bitmask & CURRY_FLAG,
 
10903         newHolders = isCurry ? holders : undefined,
 
10904         newHoldersRight = isCurry ? undefined : holders,
 
10905         newPartials = isCurry ? partials : undefined,
 
10906         newPartialsRight = isCurry ? undefined : partials;
 
10908     bitmask |= (isCurry ? PARTIAL_FLAG : PARTIAL_RIGHT_FLAG);
 
10909     bitmask &= ~(isCurry ? PARTIAL_RIGHT_FLAG : PARTIAL_FLAG);
 
10911     if (!(bitmask & CURRY_BOUND_FLAG)) {
 
10912       bitmask &= ~(BIND_FLAG | BIND_KEY_FLAG);
 
10915       func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,
 
10916       newHoldersRight, argPos, ary, arity
 
10919     var result = wrapFunc.apply(undefined, newData);
 
10920     if (isLaziable(func)) {
 
10921       setData(result, newData);
 
10923     result.placeholder = placeholder;
 
10928    * Creates a set of `values`.
 
10931    * @param {Array} values The values to add to the set.
 
10932    * @returns {Object} Returns the new set.
 
10934   var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {
 
10935     return new Set(values);
 
10939    * Creates a `_.toPairs` or `_.toPairsIn` function.
 
10942    * @param {Function} keysFunc The function to get the keys of a given object.
 
10943    * @returns {Function} Returns the new pairs function.
 
10945   function createToPairs(keysFunc) {
 
10946     return function(object) {
 
10947       var tag = getTag(object);
 
10948       if (tag == mapTag) {
 
10949         return mapToArray(object);
 
10951       if (tag == setTag) {
 
10952         return setToPairs(object);
 
10954       return baseToPairs(object, keysFunc(object));
 
10959    * Creates a function that either curries or invokes `func` with optional
 
10960    * `this` binding and partially applied arguments.
 
10963    * @param {Function|string} func The function or method name to wrap.
 
10964    * @param {number} bitmask The bitmask of wrapper flags.
 
10965    *  The bitmask may be composed of the following flags:
 
10968    *     4 - `_.curry` or `_.curryRight` of a bound function
 
10970    *    16 - `_.curryRight`
 
10972    *    64 - `_.partialRight`
 
10976    * @param {*} [thisArg] The `this` binding of `func`.
 
10977    * @param {Array} [partials] The arguments to be partially applied.
 
10978    * @param {Array} [holders] The `partials` placeholder indexes.
 
10979    * @param {Array} [argPos] The argument positions of the new function.
 
10980    * @param {number} [ary] The arity cap of `func`.
 
10981    * @param {number} [arity] The arity of `func`.
 
10982    * @returns {Function} Returns the new wrapped function.
 
10984   function createWrapper(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
 
10985     var isBindKey = bitmask & BIND_KEY_FLAG;
 
10986     if (!isBindKey && typeof func != 'function') {
 
10987       throw new TypeError(FUNC_ERROR_TEXT);
 
10989     var length = partials ? partials.length : 0;
 
10991       bitmask &= ~(PARTIAL_FLAG | PARTIAL_RIGHT_FLAG);
 
10992       partials = holders = undefined;
 
10994     ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0);
 
10995     arity = arity === undefined ? arity : toInteger(arity);
 
10996     length -= holders ? holders.length : 0;
 
10998     if (bitmask & PARTIAL_RIGHT_FLAG) {
 
10999       var partialsRight = partials,
 
11000           holdersRight = holders;
 
11002       partials = holders = undefined;
 
11004     var data = isBindKey ? undefined : getData(func);
 
11007       func, bitmask, thisArg, partials, holders, partialsRight, holdersRight,
 
11012       mergeData(newData, data);
 
11015     bitmask = newData[1];
 
11016     thisArg = newData[2];
 
11017     partials = newData[3];
 
11018     holders = newData[4];
 
11019     arity = newData[9] = newData[9] == null
 
11020       ? (isBindKey ? 0 : func.length)
 
11021       : nativeMax(newData[9] - length, 0);
 
11023     if (!arity && bitmask & (CURRY_FLAG | CURRY_RIGHT_FLAG)) {
 
11024       bitmask &= ~(CURRY_FLAG | CURRY_RIGHT_FLAG);
 
11026     if (!bitmask || bitmask == BIND_FLAG) {
 
11027       var result = createBaseWrapper(func, bitmask, thisArg);
 
11028     } else if (bitmask == CURRY_FLAG || bitmask == CURRY_RIGHT_FLAG) {
 
11029       result = createCurryWrapper(func, bitmask, arity);
 
11030     } else if ((bitmask == PARTIAL_FLAG || bitmask == (BIND_FLAG | PARTIAL_FLAG)) && !holders.length) {
 
11031       result = createPartialWrapper(func, bitmask, thisArg, partials);
 
11033       result = createHybridWrapper.apply(undefined, newData);
 
11035     var setter = data ? baseSetData : setData;
 
11036     return setter(result, newData);
 
11040    * A specialized version of `baseIsEqualDeep` for arrays with support for
 
11041    * partial deep comparisons.
 
11044    * @param {Array} array The array to compare.
 
11045    * @param {Array} other The other array to compare.
 
11046    * @param {Function} equalFunc The function to determine equivalents of values.
 
11047    * @param {Function} customizer The function to customize comparisons.
 
11048    * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`
 
11049    *  for more details.
 
11050    * @param {Object} stack Tracks traversed `array` and `other` objects.
 
11051    * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
 
11053   function equalArrays(array, other, equalFunc, customizer, bitmask, stack) {
 
11054     var isPartial = bitmask & PARTIAL_COMPARE_FLAG,
 
11055         arrLength = array.length,
 
11056         othLength = other.length;
 
11058     if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
 
11061     // Assume cyclic values are equal.
 
11062     var stacked = stack.get(array);
 
11064       return stacked == other;
 
11068         seen = (bitmask & UNORDERED_COMPARE_FLAG) ? new SetCache : undefined;
 
11070     stack.set(array, other);
 
11072     // Ignore non-index properties.
 
11073     while (++index < arrLength) {
 
11074       var arrValue = array[index],
 
11075           othValue = other[index];
 
11078         var compared = isPartial
 
11079           ? customizer(othValue, arrValue, index, other, array, stack)
 
11080           : customizer(arrValue, othValue, index, array, other, stack);
 
11082       if (compared !== undefined) {
 
11089       // Recursively compare arrays (susceptible to call stack limits).
 
11091         if (!arraySome(other, function(othValue, othIndex) {
 
11092               if (!seen.has(othIndex) &&
 
11093                   (arrValue === othValue || equalFunc(arrValue, othValue, customizer, bitmask, stack))) {
 
11094                 return seen.add(othIndex);
 
11101             arrValue === othValue ||
 
11102               equalFunc(arrValue, othValue, customizer, bitmask, stack)
 
11108     stack['delete'](array);
 
11113    * A specialized version of `baseIsEqualDeep` for comparing objects of
 
11114    * the same `toStringTag`.
 
11116    * **Note:** This function only supports comparing values with tags of
 
11117    * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
 
11120    * @param {Object} object The object to compare.
 
11121    * @param {Object} other The other object to compare.
 
11122    * @param {string} tag The `toStringTag` of the objects to compare.
 
11123    * @param {Function} equalFunc The function to determine equivalents of values.
 
11124    * @param {Function} customizer The function to customize comparisons.
 
11125    * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`
 
11126    *  for more details.
 
11127    * @param {Object} stack Tracks traversed `object` and `other` objects.
 
11128    * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 
11130   function equalByTag(object, other, tag, equalFunc, customizer, bitmask, stack) {
 
11133         if ((object.byteLength != other.byteLength) ||
 
11134             (object.byteOffset != other.byteOffset)) {
 
11137         object = object.buffer;
 
11138         other = other.buffer;
 
11140       case arrayBufferTag:
 
11141         if ((object.byteLength != other.byteLength) ||
 
11142             !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
 
11149         // Coerce dates and booleans to numbers, dates to milliseconds and
 
11150         // booleans to `1` or `0` treating invalid dates coerced to `NaN` as
 
11152         return +object == +other;
 
11155         return object.name == other.name && object.message == other.message;
 
11158         // Treat `NaN` vs. `NaN` as equal.
 
11159         return (object != +object) ? other != +other : object == +other;
 
11163         // Coerce regexes to strings and treat strings, primitives and objects,
 
11164         // as equal. See http://www.ecma-international.org/ecma-262/6.0/#sec-regexp.prototype.tostring
 
11165         // for more details.
 
11166         return object == (other + '');
 
11169         var convert = mapToArray;
 
11172         var isPartial = bitmask & PARTIAL_COMPARE_FLAG;
 
11173         convert || (convert = setToArray);
 
11175         if (object.size != other.size && !isPartial) {
 
11178         // Assume cyclic values are equal.
 
11179         var stacked = stack.get(object);
 
11181           return stacked == other;
 
11183         bitmask |= UNORDERED_COMPARE_FLAG;
 
11184         stack.set(object, other);
 
11186         // Recursively compare objects (susceptible to call stack limits).
 
11187         return equalArrays(convert(object), convert(other), equalFunc, customizer, bitmask, stack);
 
11190         if (symbolValueOf) {
 
11191           return symbolValueOf.call(object) == symbolValueOf.call(other);
 
11198    * A specialized version of `baseIsEqualDeep` for objects with support for
 
11199    * partial deep comparisons.
 
11202    * @param {Object} object The object to compare.
 
11203    * @param {Object} other The other object to compare.
 
11204    * @param {Function} equalFunc The function to determine equivalents of values.
 
11205    * @param {Function} customizer The function to customize comparisons.
 
11206    * @param {number} bitmask The bitmask of comparison flags. See `baseIsEqual`
 
11207    *  for more details.
 
11208    * @param {Object} stack Tracks traversed `object` and `other` objects.
 
11209    * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
 
11211   function equalObjects(object, other, equalFunc, customizer, bitmask, stack) {
 
11212     var isPartial = bitmask & PARTIAL_COMPARE_FLAG,
 
11213         objProps = keys(object),
 
11214         objLength = objProps.length,
 
11215         othProps = keys(other),
 
11216         othLength = othProps.length;
 
11218     if (objLength != othLength && !isPartial) {
 
11221     var index = objLength;
 
11223       var key = objProps[index];
 
11224       if (!(isPartial ? key in other : baseHas(other, key))) {
 
11228     // Assume cyclic values are equal.
 
11229     var stacked = stack.get(object);
 
11231       return stacked == other;
 
11234     stack.set(object, other);
 
11236     var skipCtor = isPartial;
 
11237     while (++index < objLength) {
 
11238       key = objProps[index];
 
11239       var objValue = object[key],
 
11240           othValue = other[key];
 
11243         var compared = isPartial
 
11244           ? customizer(othValue, objValue, key, other, object, stack)
 
11245           : customizer(objValue, othValue, key, object, other, stack);
 
11247       // Recursively compare objects (susceptible to call stack limits).
 
11248       if (!(compared === undefined
 
11249             ? (objValue === othValue || equalFunc(objValue, othValue, customizer, bitmask, stack))
 
11255       skipCtor || (skipCtor = key == 'constructor');
 
11257     if (result && !skipCtor) {
 
11258       var objCtor = object.constructor,
 
11259           othCtor = other.constructor;
 
11261       // Non `Object` object instances with different constructors are not equal.
 
11262       if (objCtor != othCtor &&
 
11263           ('constructor' in object && 'constructor' in other) &&
 
11264           !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
 
11265             typeof othCtor == 'function' && othCtor instanceof othCtor)) {
 
11269     stack['delete'](object);
 
11274    * Creates an array of own enumerable property names and symbols of `object`.
 
11277    * @param {Object} object The object to query.
 
11278    * @returns {Array} Returns the array of property names and symbols.
 
11280   function getAllKeys(object) {
 
11281     return baseGetAllKeys(object, keys, getSymbols);
 
11285    * Creates an array of own and inherited enumerable property names and
 
11286    * symbols of `object`.
 
11289    * @param {Object} object The object to query.
 
11290    * @returns {Array} Returns the array of property names and symbols.
 
11292   function getAllKeysIn(object) {
 
11293     return baseGetAllKeys(object, keysIn, getSymbolsIn);
 
11297    * Gets metadata for `func`.
 
11300    * @param {Function} func The function to query.
 
11301    * @returns {*} Returns the metadata for `func`.
 
11303   var getData = !metaMap ? noop : function(func) {
 
11304     return metaMap.get(func);
 
11308    * Gets the name of `func`.
 
11311    * @param {Function} func The function to query.
 
11312    * @returns {string} Returns the function name.
 
11314   function getFuncName(func) {
 
11315     var result = (func.name + ''),
 
11316         array = realNames[result],
 
11317         length = hasOwnProperty.call(realNames, result) ? array.length : 0;
 
11320       var data = array[length],
 
11321           otherFunc = data.func;
 
11322       if (otherFunc == null || otherFunc == func) {
 
11330    * Gets the argument placeholder value for `func`.
 
11333    * @param {Function} func The function to inspect.
 
11334    * @returns {*} Returns the placeholder value.
 
11336   function getHolder(func) {
 
11337     var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;
 
11338     return object.placeholder;
 
11342    * Gets the appropriate "iteratee" function. If `_.iteratee` is customized,
 
11343    * this function returns the custom method, otherwise it returns `baseIteratee`.
 
11344    * If arguments are provided, the chosen function is invoked with them and
 
11345    * its result is returned.
 
11348    * @param {*} [value] The value to convert to an iteratee.
 
11349    * @param {number} [arity] The arity of the created iteratee.
 
11350    * @returns {Function} Returns the chosen function or its result.
 
11352   function getIteratee() {
 
11353     var result = lodash.iteratee || iteratee;
 
11354     result = result === iteratee ? baseIteratee : result;
 
11355     return arguments.length ? result(arguments[0], arguments[1]) : result;
 
11359    * Gets the "length" property value of `object`.
 
11361    * **Note:** This function is used to avoid a
 
11362    * [JIT bug](https://bugs.webkit.org/show_bug.cgi?id=142792) that affects
 
11363    * Safari on at least iOS 8.1-8.3 ARM64.
 
11366    * @param {Object} object The object to query.
 
11367    * @returns {*} Returns the "length" value.
 
11369   var getLength = baseProperty('length');
 
11372    * Gets the data for `map`.
 
11375    * @param {Object} map The map to query.
 
11376    * @param {string} key The reference key.
 
11377    * @returns {*} Returns the map data.
 
11379   function getMapData(map, key) {
 
11380     var data = map.__data__;
 
11381     return isKeyable(key)
 
11382       ? data[typeof key == 'string' ? 'string' : 'hash']
 
11387    * Gets the property names, values, and compare flags of `object`.
 
11390    * @param {Object} object The object to query.
 
11391    * @returns {Array} Returns the match data of `object`.
 
11393   function getMatchData(object) {
 
11394     var result = toPairs(object),
 
11395         length = result.length;
 
11398       result[length][2] = isStrictComparable(result[length][1]);
 
11404    * Gets the native function at `key` of `object`.
 
11407    * @param {Object} object The object to query.
 
11408    * @param {string} key The key of the method to get.
 
11409    * @returns {*} Returns the function if it's native, else `undefined`.
 
11411   function getNative(object, key) {
 
11412     var value = object[key];
 
11413     return isNative(value) ? value : undefined;
 
11417    * Gets the `[[Prototype]]` of `value`.
 
11420    * @param {*} value The value to query.
 
11421    * @returns {null|Object} Returns the `[[Prototype]]`.
 
11423   function getPrototype(value) {
 
11424     return nativeGetPrototype(Object(value));
 
11428    * Creates an array of the own enumerable symbol properties of `object`.
 
11431    * @param {Object} object The object to query.
 
11432    * @returns {Array} Returns the array of symbols.
 
11434   function getSymbols(object) {
 
11435     // Coerce `object` to an object to avoid non-object errors in V8.
 
11436     // See https://bugs.chromium.org/p/v8/issues/detail?id=3443 for more details.
 
11437     return getOwnPropertySymbols(Object(object));
 
11440   // Fallback for IE < 11.
 
11441   if (!getOwnPropertySymbols) {
 
11442     getSymbols = function() {
 
11448    * Creates an array of the own and inherited enumerable symbol properties
 
11452    * @param {Object} object The object to query.
 
11453    * @returns {Array} Returns the array of symbols.
 
11455   var getSymbolsIn = !getOwnPropertySymbols ? getSymbols : function(object) {
 
11458       arrayPush(result, getSymbols(object));
 
11459       object = getPrototype(object);
 
11465    * Gets the `toStringTag` of `value`.
 
11468    * @param {*} value The value to query.
 
11469    * @returns {string} Returns the `toStringTag`.
 
11471   function getTag(value) {
 
11472     return objectToString.call(value);
 
11475   // Fallback for data views, maps, sets, and weak maps in IE 11,
 
11476   // for data views in Edge, and promises in Node.js.
 
11477   if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
 
11478       (Map && getTag(new Map) != mapTag) ||
 
11479       (Promise && getTag(Promise.resolve()) != promiseTag) ||
 
11480       (Set && getTag(new Set) != setTag) ||
 
11481       (WeakMap && getTag(new WeakMap) != weakMapTag)) {
 
11482     getTag = function(value) {
 
11483       var result = objectToString.call(value),
 
11484           Ctor = result == objectTag ? value.constructor : undefined,
 
11485           ctorString = Ctor ? toSource(Ctor) : undefined;
 
11488         switch (ctorString) {
 
11489           case dataViewCtorString: return dataViewTag;
 
11490           case mapCtorString: return mapTag;
 
11491           case promiseCtorString: return promiseTag;
 
11492           case setCtorString: return setTag;
 
11493           case weakMapCtorString: return weakMapTag;
 
11501    * Gets the view, applying any `transforms` to the `start` and `end` positions.
 
11504    * @param {number} start The start of the view.
 
11505    * @param {number} end The end of the view.
 
11506    * @param {Array} transforms The transformations to apply to the view.
 
11507    * @returns {Object} Returns an object containing the `start` and `end`
 
11508    *  positions of the view.
 
11510   function getView(start, end, transforms) {
 
11512         length = transforms.length;
 
11514     while (++index < length) {
 
11515       var data = transforms[index],
 
11518       switch (data.type) {
 
11519         case 'drop':      start += size; break;
 
11520         case 'dropRight': end -= size; break;
 
11521         case 'take':      end = nativeMin(end, start + size); break;
 
11522         case 'takeRight': start = nativeMax(start, end - size); break;
 
11525     return { 'start': start, 'end': end };
 
11529    * Checks if `path` exists on `object`.
 
11532    * @param {Object} object The object to query.
 
11533    * @param {Array|string} path The path to check.
 
11534    * @param {Function} hasFunc The function to check properties.
 
11535    * @returns {boolean} Returns `true` if `path` exists, else `false`.
 
11537   function hasPath(object, path, hasFunc) {
 
11538     path = isKey(path, object) ? [path] : castPath(path);
 
11542         length = path.length;
 
11544     while (++index < length) {
 
11545       var key = toKey(path[index]);
 
11546       if (!(result = object != null && hasFunc(object, key))) {
 
11549       object = object[key];
 
11554     var length = object ? object.length : 0;
 
11555     return !!length && isLength(length) && isIndex(key, length) &&
 
11556       (isArray(object) || isString(object) || isArguments(object));
 
11560    * Initializes an array clone.
 
11563    * @param {Array} array The array to clone.
 
11564    * @returns {Array} Returns the initialized clone.
 
11566   function initCloneArray(array) {
 
11567     var length = array.length,
 
11568         result = array.constructor(length);
 
11570     // Add properties assigned by `RegExp#exec`.
 
11571     if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
 
11572       result.index = array.index;
 
11573       result.input = array.input;
 
11579    * Initializes an object clone.
 
11582    * @param {Object} object The object to clone.
 
11583    * @returns {Object} Returns the initialized clone.
 
11585   function initCloneObject(object) {
 
11586     return (typeof object.constructor == 'function' && !isPrototype(object))
 
11587       ? baseCreate(getPrototype(object))
 
11592    * Initializes an object clone based on its `toStringTag`.
 
11594    * **Note:** This function only supports cloning values with tags of
 
11595    * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
 
11598    * @param {Object} object The object to clone.
 
11599    * @param {string} tag The `toStringTag` of the object to clone.
 
11600    * @param {Function} cloneFunc The function to clone values.
 
11601    * @param {boolean} [isDeep] Specify a deep clone.
 
11602    * @returns {Object} Returns the initialized clone.
 
11604   function initCloneByTag(object, tag, cloneFunc, isDeep) {
 
11605     var Ctor = object.constructor;
 
11607       case arrayBufferTag:
 
11608         return cloneArrayBuffer(object);
 
11612         return new Ctor(+object);
 
11615         return cloneDataView(object, isDeep);
 
11617       case float32Tag: case float64Tag:
 
11618       case int8Tag: case int16Tag: case int32Tag:
 
11619       case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
 
11620         return cloneTypedArray(object, isDeep);
 
11623         return cloneMap(object, isDeep, cloneFunc);
 
11627         return new Ctor(object);
 
11630         return cloneRegExp(object);
 
11633         return cloneSet(object, isDeep, cloneFunc);
 
11636         return cloneSymbol(object);
 
11641    * Creates an array of index keys for `object` values of arrays,
 
11642    * `arguments` objects, and strings, otherwise `null` is returned.
 
11645    * @param {Object} object The object to query.
 
11646    * @returns {Array|null} Returns index keys, else `null`.
 
11648   function indexKeys(object) {
 
11649     var length = object ? object.length : undefined;
 
11650     if (isLength(length) &&
 
11651         (isArray(object) || isString(object) || isArguments(object))) {
 
11652       return baseTimes(length, String);
 
11658    * Checks if `value` is a flattenable `arguments` object or array.
 
11661    * @param {*} value The value to check.
 
11662    * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
 
11664   function isFlattenable(value) {
 
11665     return isArray(value) || isArguments(value);
 
11669    * Checks if `value` is a valid array-like index.
 
11672    * @param {*} value The value to check.
 
11673    * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
 
11674    * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
 
11676   function isIndex(value, length) {
 
11677     length = length == null ? MAX_SAFE_INTEGER : length;
 
11679       (typeof value == 'number' || reIsUint.test(value)) &&
 
11680       (value > -1 && value % 1 == 0 && value < length);
 
11684    * Checks if the given arguments are from an iteratee call.
 
11687    * @param {*} value The potential iteratee value argument.
 
11688    * @param {*} index The potential iteratee index or key argument.
 
11689    * @param {*} object The potential iteratee object argument.
 
11690    * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
 
11693   function isIterateeCall(value, index, object) {
 
11694     if (!isObject(object)) {
 
11697     var type = typeof index;
 
11698     if (type == 'number'
 
11699           ? (isArrayLike(object) && isIndex(index, object.length))
 
11700           : (type == 'string' && index in object)
 
11702       return eq(object[index], value);
 
11708    * Checks if `value` is a property name and not a property path.
 
11711    * @param {*} value The value to check.
 
11712    * @param {Object} [object] The object to query keys on.
 
11713    * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
 
11715   function isKey(value, object) {
 
11716     if (isArray(value)) {
 
11719     var type = typeof value;
 
11720     if (type == 'number' || type == 'symbol' || type == 'boolean' ||
 
11721         value == null || isSymbol(value)) {
 
11724     return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
 
11725       (object != null && value in Object(object));
 
11729    * Checks if `value` is suitable for use as unique object key.
 
11732    * @param {*} value The value to check.
 
11733    * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
 
11735   function isKeyable(value) {
 
11736     var type = typeof value;
 
11737     return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
 
11738       ? (value !== '__proto__')
 
11739       : (value === null);
 
11743    * Checks if `func` has a lazy counterpart.
 
11746    * @param {Function} func The function to check.
 
11747    * @returns {boolean} Returns `true` if `func` has a lazy counterpart,
 
11750   function isLaziable(func) {
 
11751     var funcName = getFuncName(func),
 
11752         other = lodash[funcName];
 
11754     if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {
 
11757     if (func === other) {
 
11760     var data = getData(other);
 
11761     return !!data && func === data[0];
 
11765    * Checks if `value` is likely a prototype object.
 
11768    * @param {*} value The value to check.
 
11769    * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
 
11771   function isPrototype(value) {
 
11772     var Ctor = value && value.constructor,
 
11773         proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
 
11775     return value === proto;
 
11779    * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
 
11782    * @param {*} value The value to check.
 
11783    * @returns {boolean} Returns `true` if `value` if suitable for strict
 
11784    *  equality comparisons, else `false`.
 
11786   function isStrictComparable(value) {
 
11787     return value === value && !isObject(value);
 
11791    * A specialized version of `matchesProperty` for source values suitable
 
11792    * for strict equality comparisons, i.e. `===`.
 
11795    * @param {string} key The key of the property to get.
 
11796    * @param {*} srcValue The value to match.
 
11797    * @returns {Function} Returns the new spec function.
 
11799   function matchesStrictComparable(key, srcValue) {
 
11800     return function(object) {
 
11801       if (object == null) {
 
11804       return object[key] === srcValue &&
 
11805         (srcValue !== undefined || (key in Object(object)));
 
11810    * Merges the function metadata of `source` into `data`.
 
11812    * Merging metadata reduces the number of wrappers used to invoke a function.
 
11813    * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
 
11814    * may be applied regardless of execution order. Methods like `_.ary` and
 
11815    * `_.rearg` modify function arguments, making the order in which they are
 
11816    * executed important, preventing the merging of metadata. However, we make
 
11817    * an exception for a safe combined case where curried functions have `_.ary`
 
11818    * and or `_.rearg` applied.
 
11821    * @param {Array} data The destination metadata.
 
11822    * @param {Array} source The source metadata.
 
11823    * @returns {Array} Returns `data`.
 
11825   function mergeData(data, source) {
 
11826     var bitmask = data[1],
 
11827         srcBitmask = source[1],
 
11828         newBitmask = bitmask | srcBitmask,
 
11829         isCommon = newBitmask < (BIND_FLAG | BIND_KEY_FLAG | ARY_FLAG);
 
11832       ((srcBitmask == ARY_FLAG) && (bitmask == CURRY_FLAG)) ||
 
11833       ((srcBitmask == ARY_FLAG) && (bitmask == REARG_FLAG) && (data[7].length <= source[8])) ||
 
11834       ((srcBitmask == (ARY_FLAG | REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == CURRY_FLAG));
 
11836     // Exit early if metadata can't be merged.
 
11837     if (!(isCommon || isCombo)) {
 
11840     // Use source `thisArg` if available.
 
11841     if (srcBitmask & BIND_FLAG) {
 
11842       data[2] = source[2];
 
11843       // Set when currying a bound function.
 
11844       newBitmask |= bitmask & BIND_FLAG ? 0 : CURRY_BOUND_FLAG;
 
11846     // Compose partial arguments.
 
11847     var value = source[3];
 
11849       var partials = data[3];
 
11850       data[3] = partials ? composeArgs(partials, value, source[4]) : value;
 
11851       data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];
 
11853     // Compose partial right arguments.
 
11856       partials = data[5];
 
11857       data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;
 
11858       data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];
 
11860     // Use source `argPos` if available.
 
11865     // Use source `ary` if it's smaller.
 
11866     if (srcBitmask & ARY_FLAG) {
 
11867       data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
 
11869     // Use source `arity` if one is not provided.
 
11870     if (data[9] == null) {
 
11871       data[9] = source[9];
 
11873     // Use source `func` and merge bitmasks.
 
11874     data[0] = source[0];
 
11875     data[1] = newBitmask;
 
11881    * Gets the parent value at `path` of `object`.
 
11884    * @param {Object} object The object to query.
 
11885    * @param {Array} path The path to get the parent value of.
 
11886    * @returns {*} Returns the parent value.
 
11888   function parent(object, path) {
 
11889     return path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
 
11893    * Reorder `array` according to the specified indexes where the element at
 
11894    * the first index is assigned as the first element, the element at
 
11895    * the second index is assigned as the second element, and so on.
 
11898    * @param {Array} array The array to reorder.
 
11899    * @param {Array} indexes The arranged array indexes.
 
11900    * @returns {Array} Returns `array`.
 
11902   function reorder(array, indexes) {
 
11903     var arrLength = array.length,
 
11904         length = nativeMin(indexes.length, arrLength),
 
11905         oldArray = copyArray(array);
 
11908       var index = indexes[length];
 
11909       array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
 
11915    * Sets metadata for `func`.
 
11917    * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
 
11918    * period of time, it will trip its breaker and transition to an identity
 
11919    * function to avoid garbage collection pauses in V8. See
 
11920    * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070)
 
11921    * for more details.
 
11924    * @param {Function} func The function to associate metadata with.
 
11925    * @param {*} data The metadata.
 
11926    * @returns {Function} Returns `func`.
 
11928   var setData = (function() {
 
11932     return function(key, value) {
 
11934           remaining = HOT_SPAN - (stamp - lastCalled);
 
11936       lastCalled = stamp;
 
11937       if (remaining > 0) {
 
11938         if (++count >= HOT_COUNT) {
 
11944       return baseSetData(key, value);
 
11949    * Converts `string` to a property path array.
 
11952    * @param {string} string The string to convert.
 
11953    * @returns {Array} Returns the property path array.
 
11955   var stringToPath = memoize(function(string) {
 
11957     toString(string).replace(rePropName, function(match, number, quote, string) {
 
11958       result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
 
11964    * Converts `value` to a string key if it's not a string or symbol.
 
11967    * @param {*} value The value to inspect.
 
11968    * @returns {string|symbol} Returns the key.
 
11970   function toKey(value) {
 
11971     if (typeof value == 'string' || isSymbol(value)) {
 
11974     var result = (value + '');
 
11975     return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
 
11979    * Converts `func` to its source code.
 
11982    * @param {Function} func The function to process.
 
11983    * @returns {string} Returns the source code.
 
11985   function toSource(func) {
 
11986     if (func != null) {
 
11988         return funcToString.call(func);
 
11991         return (func + '');
 
11998    * Creates a clone of `wrapper`.
 
12001    * @param {Object} wrapper The wrapper to clone.
 
12002    * @returns {Object} Returns the cloned wrapper.
 
12004   function wrapperClone(wrapper) {
 
12005     if (wrapper instanceof LazyWrapper) {
 
12006       return wrapper.clone();
 
12008     var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
 
12009     result.__actions__ = copyArray(wrapper.__actions__);
 
12010     result.__index__  = wrapper.__index__;
 
12011     result.__values__ = wrapper.__values__;
 
12015   /*------------------------------------------------------------------------*/
 
12018    * Creates an array of elements split into groups the length of `size`.
 
12019    * If `array` can't be split evenly, the final chunk will be the remaining
 
12026    * @param {Array} array The array to process.
 
12027    * @param {number} [size=1] The length of each chunk
 
12028    * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
 
12029    * @returns {Array} Returns the new array of chunks.
 
12032    * _.chunk(['a', 'b', 'c', 'd'], 2);
 
12033    * // => [['a', 'b'], ['c', 'd']]
 
12035    * _.chunk(['a', 'b', 'c', 'd'], 3);
 
12036    * // => [['a', 'b', 'c'], ['d']]
 
12038   function chunk(array, size, guard) {
 
12039     if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) {
 
12042       size = nativeMax(toInteger(size), 0);
 
12044     var length = array ? array.length : 0;
 
12045     if (!length || size < 1) {
 
12050         result = Array(nativeCeil(length / size));
 
12052     while (index < length) {
 
12053       result[resIndex++] = baseSlice(array, index, (index += size));
 
12059    * Creates an array with all falsey values removed. The values `false`, `null`,
 
12060    * `0`, `""`, `undefined`, and `NaN` are falsey.
 
12066    * @param {Array} array The array to compact.
 
12067    * @returns {Array} Returns the new array of filtered values.
 
12070    * _.compact([0, 1, false, 2, '', 3]);
 
12073   function compact(array) {
 
12075         length = array ? array.length : 0,
 
12079     while (++index < length) {
 
12080       var value = array[index];
 
12082         result[resIndex++] = value;
 
12089    * Creates an array of unique `array` values not included in the other given
 
12090    * arrays using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
 
12091    * for equality comparisons. The order of result values is determined by the
 
12092    * order they occur in the first array.
 
12098    * @param {Array} array The array to inspect.
 
12099    * @param {...Array} [values] The values to exclude.
 
12100    * @returns {Array} Returns the new array of filtered values.
 
12101    * @see _.without, _.xor
 
12104    * _.difference([3, 2, 1], [4, 2]);
 
12107   var difference = rest(function(array, values) {
 
12108     return isArrayLikeObject(array)
 
12109       ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))
 
12114    * Flattens `array` a single level deep.
 
12120    * @param {Array} array The array to flatten.
 
12121    * @returns {Array} Returns the new flattened array.
 
12124    * _.flatten([1, [2, [3, [4]], 5]]);
 
12125    * // => [1, 2, [3, [4]], 5]
 
12127   function flatten(array) {
 
12128     var length = array ? array.length : 0;
 
12129     return length ? baseFlatten(array, 1) : [];
 
12133    * Gets the first element of `array`.
 
12140    * @param {Array} array The array to query.
 
12141    * @returns {*} Returns the first element of `array`.
 
12144    * _.head([1, 2, 3]);
 
12150   function head(array) {
 
12151     return (array && array.length) ? array[0] : undefined;
 
12155    * Gets the index at which the first occurrence of `value` is found in `array`
 
12156    * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
 
12157    * for equality comparisons. If `fromIndex` is negative, it's used as the
 
12158    * offset from the end of `array`.
 
12164    * @param {Array} array The array to search.
 
12165    * @param {*} value The value to search for.
 
12166    * @param {number} [fromIndex=0] The index to search from.
 
12167    * @returns {number} Returns the index of the matched value, else `-1`.
 
12170    * _.indexOf([1, 2, 1, 2], 2);
 
12173    * // Search from the `fromIndex`.
 
12174    * _.indexOf([1, 2, 1, 2], 2, 2);
 
12177   function indexOf(array, value, fromIndex) {
 
12178     var length = array ? array.length : 0;
 
12182     fromIndex = toInteger(fromIndex);
 
12183     if (fromIndex < 0) {
 
12184       fromIndex = nativeMax(length + fromIndex, 0);
 
12186     return baseIndexOf(array, value, fromIndex);
 
12190    * Creates an array of unique values that are included in all given arrays
 
12191    * using [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
 
12192    * for equality comparisons. The order of result values is determined by the
 
12193    * order they occur in the first array.
 
12199    * @param {...Array} [arrays] The arrays to inspect.
 
12200    * @returns {Array} Returns the new array of intersecting values.
 
12203    * _.intersection([2, 1], [4, 2], [1, 2]);
 
12206   var intersection = rest(function(arrays) {
 
12207     var mapped = arrayMap(arrays, castArrayLikeObject);
 
12208     return (mapped.length && mapped[0] === arrays[0])
 
12209       ? baseIntersection(mapped)
 
12214    * Gets the last element of `array`.
 
12220    * @param {Array} array The array to query.
 
12221    * @returns {*} Returns the last element of `array`.
 
12224    * _.last([1, 2, 3]);
 
12227   function last(array) {
 
12228     var length = array ? array.length : 0;
 
12229     return length ? array[length - 1] : undefined;
 
12233    * Reverses `array` so that the first element becomes the last, the second
 
12234    * element becomes the second to last, and so on.
 
12236    * **Note:** This method mutates `array` and is based on
 
12237    * [`Array#reverse`](https://mdn.io/Array/reverse).
 
12243    * @param {Array} array The array to modify.
 
12244    * @returns {Array} Returns `array`.
 
12247    * var array = [1, 2, 3];
 
12249    * _.reverse(array);
 
12252    * console.log(array);
 
12255   function reverse(array) {
 
12256     return array ? nativeReverse.call(array) : array;
 
12260    * Creates an array of unique values, in order, from all given arrays using
 
12261    * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
 
12262    * for equality comparisons.
 
12268    * @param {...Array} [arrays] The arrays to inspect.
 
12269    * @returns {Array} Returns the new array of combined values.
 
12272    * _.union([2, 1], [4, 2], [1, 2]);
 
12275   var union = rest(function(arrays) {
 
12276     return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
 
12280    * Creates a duplicate-free version of an array, using
 
12281    * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
 
12282    * for equality comparisons, in which only the first occurrence of each
 
12289    * @param {Array} array The array to inspect.
 
12290    * @returns {Array} Returns the new duplicate free array.
 
12293    * _.uniq([2, 1, 2]);
 
12296   function uniq(array) {
 
12297     return (array && array.length)
 
12303    * Creates an array excluding all given values using
 
12304    * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
 
12305    * for equality comparisons.
 
12311    * @param {Array} array The array to inspect.
 
12312    * @param {...*} [values] The values to exclude.
 
12313    * @returns {Array} Returns the new array of filtered values.
 
12314    * @see _.difference, _.xor
 
12317    * _.without([1, 2, 1, 3], 1, 2);
 
12320   var without = rest(function(array, values) {
 
12321     return isArrayLikeObject(array)
 
12322       ? baseDifference(array, values)
 
12326   /*------------------------------------------------------------------------*/
 
12329    * Creates a `lodash` wrapper instance that wraps `value` with explicit method
 
12330    * chain sequences enabled. The result of such sequences must be unwrapped
 
12337    * @param {*} value The value to wrap.
 
12338    * @returns {Object} Returns the new `lodash` wrapper instance.
 
12342    *   { 'user': 'barney',  'age': 36 },
 
12343    *   { 'user': 'fred',    'age': 40 },
 
12344    *   { 'user': 'pebbles', 'age': 1 }
 
12350    *   .map(function(o) {
 
12351    *     return o.user + ' is ' + o.age;
 
12355    * // => 'pebbles is 1'
 
12357   function chain(value) {
 
12358     var result = lodash(value);
 
12359     result.__chain__ = true;
 
12364    * This method invokes `interceptor` and returns `value`. The interceptor
 
12365    * is invoked with one argument; (value). The purpose of this method is to
 
12366    * "tap into" a method chain sequence in order to modify intermediate results.
 
12372    * @param {*} value The value to provide to `interceptor`.
 
12373    * @param {Function} interceptor The function to invoke.
 
12374    * @returns {*} Returns `value`.
 
12378    *  .tap(function(array) {
 
12379    *    // Mutate input array.
 
12386   function tap(value, interceptor) {
 
12387     interceptor(value);
 
12392    * This method is like `_.tap` except that it returns the result of `interceptor`.
 
12393    * The purpose of this method is to "pass thru" values replacing intermediate
 
12394    * results in a method chain sequence.
 
12400    * @param {*} value The value to provide to `interceptor`.
 
12401    * @param {Function} interceptor The function to invoke.
 
12402    * @returns {*} Returns the result of `interceptor`.
 
12408    *  .thru(function(value) {
 
12414   function thru(value, interceptor) {
 
12415     return interceptor(value);
 
12419    * This method is the wrapper version of `_.at`.
 
12425    * @param {...(string|string[])} [paths] The property paths of elements to pick.
 
12426    * @returns {Object} Returns the new `lodash` wrapper instance.
 
12429    * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
 
12431    * _(object).at(['a[0].b.c', 'a[1]']).value();
 
12434    * _(['a', 'b', 'c']).at(0, 2).value();
 
12437   var wrapperAt = rest(function(paths) {
 
12438     paths = baseFlatten(paths, 1);
 
12439     var length = paths.length,
 
12440         start = length ? paths[0] : 0,
 
12441         value = this.__wrapped__,
 
12442         interceptor = function(object) { return baseAt(object, paths); };
 
12444     if (length > 1 || this.__actions__.length ||
 
12445         !(value instanceof LazyWrapper) || !isIndex(start)) {
 
12446       return this.thru(interceptor);
 
12448     value = value.slice(start, +start + (length ? 1 : 0));
 
12449     value.__actions__.push({
 
12451       'args': [interceptor],
 
12452       'thisArg': undefined
 
12454     return new LodashWrapper(value, this.__chain__).thru(function(array) {
 
12455       if (length && !array.length) {
 
12456         array.push(undefined);
 
12463    * Creates a `lodash` wrapper instance with explicit method chain sequences enabled.
 
12469    * @returns {Object} Returns the new `lodash` wrapper instance.
 
12473    *   { 'user': 'barney', 'age': 36 },
 
12474    *   { 'user': 'fred',   'age': 40 }
 
12477    * // A sequence without explicit chaining.
 
12479    * // => { 'user': 'barney', 'age': 36 }
 
12481    * // A sequence with explicit chaining.
 
12487    * // => { 'user': 'barney' }
 
12489   function wrapperChain() {
 
12490     return chain(this);
 
12494    * Executes the chain sequence and returns the wrapped result.
 
12500    * @returns {Object} Returns the new `lodash` wrapper instance.
 
12503    * var array = [1, 2];
 
12504    * var wrapped = _(array).push(3);
 
12506    * console.log(array);
 
12509    * wrapped = wrapped.commit();
 
12510    * console.log(array);
 
12516    * console.log(array);
 
12519   function wrapperCommit() {
 
12520     return new LodashWrapper(this.value(), this.__chain__);
 
12524    * Gets the next value on a wrapped object following the
 
12525    * [iterator protocol](https://mdn.io/iteration_protocols#iterator).
 
12531    * @returns {Object} Returns the next iterator value.
 
12534    * var wrapped = _([1, 2]);
 
12537    * // => { 'done': false, 'value': 1 }
 
12540    * // => { 'done': false, 'value': 2 }
 
12543    * // => { 'done': true, 'value': undefined }
 
12545   function wrapperNext() {
 
12546     if (this.__values__ === undefined) {
 
12547       this.__values__ = toArray(this.value());
 
12549     var done = this.__index__ >= this.__values__.length,
 
12550         value = done ? undefined : this.__values__[this.__index__++];
 
12552     return { 'done': done, 'value': value };
 
12556    * Enables the wrapper to be iterable.
 
12558    * @name Symbol.iterator
 
12562    * @returns {Object} Returns the wrapper object.
 
12565    * var wrapped = _([1, 2]);
 
12567    * wrapped[Symbol.iterator]() === wrapped;
 
12570    * Array.from(wrapped);
 
12573   function wrapperToIterator() {
 
12578    * Creates a clone of the chain sequence planting `value` as the wrapped value.
 
12584    * @param {*} value The value to plant.
 
12585    * @returns {Object} Returns the new `lodash` wrapper instance.
 
12588    * function square(n) {
 
12592    * var wrapped = _([1, 2]).map(square);
 
12593    * var other = wrapped.plant([3, 4]);
 
12601   function wrapperPlant(value) {
 
12605     while (parent instanceof baseLodash) {
 
12606       var clone = wrapperClone(parent);
 
12607       clone.__index__ = 0;
 
12608       clone.__values__ = undefined;
 
12610         previous.__wrapped__ = clone;
 
12614       var previous = clone;
 
12615       parent = parent.__wrapped__;
 
12617     previous.__wrapped__ = value;
 
12622    * This method is the wrapper version of `_.reverse`.
 
12624    * **Note:** This method mutates the wrapped array.
 
12630    * @returns {Object} Returns the new `lodash` wrapper instance.
 
12633    * var array = [1, 2, 3];
 
12635    * _(array).reverse().value()
 
12638    * console.log(array);
 
12641   function wrapperReverse() {
 
12642     var value = this.__wrapped__;
 
12643     if (value instanceof LazyWrapper) {
 
12644       var wrapped = value;
 
12645       if (this.__actions__.length) {
 
12646         wrapped = new LazyWrapper(this);
 
12648       wrapped = wrapped.reverse();
 
12649       wrapped.__actions__.push({
 
12652         'thisArg': undefined
 
12654       return new LodashWrapper(wrapped, this.__chain__);
 
12656     return this.thru(reverse);
 
12660    * Executes the chain sequence to resolve the unwrapped value.
 
12665    * @alias toJSON, valueOf
 
12667    * @returns {*} Returns the resolved unwrapped value.
 
12670    * _([1, 2, 3]).value();
 
12673   function wrapperValue() {
 
12674     return baseWrapperValue(this.__wrapped__, this.__actions__);
 
12677   /*------------------------------------------------------------------------*/
 
12680    * Checks if `predicate` returns truthy for **all** elements of `collection`.
 
12681    * Iteration is stopped once `predicate` returns falsey. The predicate is
 
12682    * invoked with three arguments: (value, index|key, collection).
 
12687    * @category Collection
 
12688    * @param {Array|Object} collection The collection to iterate over.
 
12689    * @param {Array|Function|Object|string} [predicate=_.identity]
 
12690    *  The function invoked per iteration.
 
12691    * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
 
12692    * @returns {boolean} Returns `true` if all elements pass the predicate check,
 
12696    * _.every([true, 1, null, 'yes'], Boolean);
 
12700    *   { 'user': 'barney', 'age': 36, 'active': false },
 
12701    *   { 'user': 'fred',   'age': 40, 'active': false }
 
12704    * // The `_.matches` iteratee shorthand.
 
12705    * _.every(users, { 'user': 'barney', 'active': false });
 
12708    * // The `_.matchesProperty` iteratee shorthand.
 
12709    * _.every(users, ['active', false]);
 
12712    * // The `_.property` iteratee shorthand.
 
12713    * _.every(users, 'active');
 
12716   function every(collection, predicate, guard) {
 
12717     var func = isArray(collection) ? arrayEvery : baseEvery;
 
12718     if (guard && isIterateeCall(collection, predicate, guard)) {
 
12719       predicate = undefined;
 
12721     return func(collection, getIteratee(predicate, 3));
 
12725    * Iterates over elements of `collection`, returning an array of all elements
 
12726    * `predicate` returns truthy for. The predicate is invoked with three
 
12727    * arguments: (value, index|key, collection).
 
12732    * @category Collection
 
12733    * @param {Array|Object} collection The collection to iterate over.
 
12734    * @param {Array|Function|Object|string} [predicate=_.identity]
 
12735    *  The function invoked per iteration.
 
12736    * @returns {Array} Returns the new filtered array.
 
12741    *   { 'user': 'barney', 'age': 36, 'active': true },
 
12742    *   { 'user': 'fred',   'age': 40, 'active': false }
 
12745    * _.filter(users, function(o) { return !o.active; });
 
12746    * // => objects for ['fred']
 
12748    * // The `_.matches` iteratee shorthand.
 
12749    * _.filter(users, { 'age': 36, 'active': true });
 
12750    * // => objects for ['barney']
 
12752    * // The `_.matchesProperty` iteratee shorthand.
 
12753    * _.filter(users, ['active', false]);
 
12754    * // => objects for ['fred']
 
12756    * // The `_.property` iteratee shorthand.
 
12757    * _.filter(users, 'active');
 
12758    * // => objects for ['barney']
 
12760   function filter(collection, predicate) {
 
12761     var func = isArray(collection) ? arrayFilter : baseFilter;
 
12762     return func(collection, getIteratee(predicate, 3));
 
12766    * Iterates over elements of `collection`, returning the first element
 
12767    * `predicate` returns truthy for. The predicate is invoked with three
 
12768    * arguments: (value, index|key, collection).
 
12773    * @category Collection
 
12774    * @param {Array|Object} collection The collection to search.
 
12775    * @param {Array|Function|Object|string} [predicate=_.identity]
 
12776    *  The function invoked per iteration.
 
12777    * @returns {*} Returns the matched element, else `undefined`.
 
12781    *   { 'user': 'barney',  'age': 36, 'active': true },
 
12782    *   { 'user': 'fred',    'age': 40, 'active': false },
 
12783    *   { 'user': 'pebbles', 'age': 1,  'active': true }
 
12786    * _.find(users, function(o) { return o.age < 40; });
 
12787    * // => object for 'barney'
 
12789    * // The `_.matches` iteratee shorthand.
 
12790    * _.find(users, { 'age': 1, 'active': true });
 
12791    * // => object for 'pebbles'
 
12793    * // The `_.matchesProperty` iteratee shorthand.
 
12794    * _.find(users, ['active', false]);
 
12795    * // => object for 'fred'
 
12797    * // The `_.property` iteratee shorthand.
 
12798    * _.find(users, 'active');
 
12799    * // => object for 'barney'
 
12801   function find(collection, predicate) {
 
12802     predicate = getIteratee(predicate, 3);
 
12803     if (isArray(collection)) {
 
12804       var index = baseFindIndex(collection, predicate);
 
12805       return index > -1 ? collection[index] : undefined;
 
12807     return baseFind(collection, predicate, baseEach);
 
12811    * Iterates over elements of `collection` and invokes `iteratee` for each element.
 
12812    * The iteratee is invoked with three arguments: (value, index|key, collection).
 
12813    * Iteratee functions may exit iteration early by explicitly returning `false`.
 
12815    * **Note:** As with other "Collections" methods, objects with a "length"
 
12816    * property are iterated like arrays. To avoid this behavior use `_.forIn`
 
12817    * or `_.forOwn` for object iteration.
 
12823    * @category Collection
 
12824    * @param {Array|Object} collection The collection to iterate over.
 
12825    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
 
12826    * @returns {Array|Object} Returns `collection`.
 
12827    * @see _.forEachRight
 
12830    * _([1, 2]).forEach(function(value) {
 
12831    *   console.log(value);
 
12833    * // => Logs `1` then `2`.
 
12835    * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
 
12836    *   console.log(key);
 
12838    * // => Logs 'a' then 'b' (iteration order is not guaranteed).
 
12840   function forEach(collection, iteratee) {
 
12841     var func = isArray(collection) ? arrayEach : baseEach;
 
12842     return func(collection, getIteratee(iteratee, 3));
 
12846    * Creates an object composed of keys generated from the results of running
 
12847    * each element of `collection` thru `iteratee`. The order of grouped values
 
12848    * is determined by the order they occur in `collection`. The corresponding
 
12849    * value of each key is an array of elements responsible for generating the
 
12850    * key. The iteratee is invoked with one argument: (value).
 
12855    * @category Collection
 
12856    * @param {Array|Object} collection The collection to iterate over.
 
12857    * @param {Array|Function|Object|string} [iteratee=_.identity]
 
12858    *  The iteratee to transform keys.
 
12859    * @returns {Object} Returns the composed aggregate object.
 
12862    * _.groupBy([6.1, 4.2, 6.3], Math.floor);
 
12863    * // => { '4': [4.2], '6': [6.1, 6.3] }
 
12865    * // The `_.property` iteratee shorthand.
 
12866    * _.groupBy(['one', 'two', 'three'], 'length');
 
12867    * // => { '3': ['one', 'two'], '5': ['three'] }
 
12869   var groupBy = createAggregator(function(result, value, key) {
 
12870     if (hasOwnProperty.call(result, key)) {
 
12871       result[key].push(value);
 
12873       result[key] = [value];
 
12878    * Checks if `value` is in `collection`. If `collection` is a string, it's
 
12879    * checked for a substring of `value`, otherwise
 
12880    * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
 
12881    * is used for equality comparisons. If `fromIndex` is negative, it's used as
 
12882    * the offset from the end of `collection`.
 
12887    * @category Collection
 
12888    * @param {Array|Object|string} collection The collection to search.
 
12889    * @param {*} value The value to search for.
 
12890    * @param {number} [fromIndex=0] The index to search from.
 
12891    * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
 
12892    * @returns {boolean} Returns `true` if `value` is found, else `false`.
 
12895    * _.includes([1, 2, 3], 1);
 
12898    * _.includes([1, 2, 3], 1, 2);
 
12901    * _.includes({ 'user': 'fred', 'age': 40 }, 'fred');
 
12904    * _.includes('pebbles', 'eb');
 
12907   function includes(collection, value, fromIndex, guard) {
 
12908     collection = isArrayLike(collection) ? collection : values(collection);
 
12909     fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0;
 
12911     var length = collection.length;
 
12912     if (fromIndex < 0) {
 
12913       fromIndex = nativeMax(length + fromIndex, 0);
 
12915     return isString(collection)
 
12916       ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1)
 
12917       : (!!length && baseIndexOf(collection, value, fromIndex) > -1);
 
12921    * Creates an array of values by running each element in `collection` thru
 
12922    * `iteratee`. The iteratee is invoked with three arguments:
 
12923    * (value, index|key, collection).
 
12925    * Many lodash methods are guarded to work as iteratees for methods like
 
12926    * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
 
12928    * The guarded methods are:
 
12929    * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,
 
12930    * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,
 
12931    * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,
 
12932    * `template`, `trim`, `trimEnd`, `trimStart`, and `words`
 
12937    * @category Collection
 
12938    * @param {Array|Object} collection The collection to iterate over.
 
12939    * @param {Array|Function|Object|string} [iteratee=_.identity]
 
12940    *  The function invoked per iteration.
 
12941    * @returns {Array} Returns the new mapped array.
 
12944    * function square(n) {
 
12948    * _.map([4, 8], square);
 
12951    * _.map({ 'a': 4, 'b': 8 }, square);
 
12952    * // => [16, 64] (iteration order is not guaranteed)
 
12955    *   { 'user': 'barney' },
 
12956    *   { 'user': 'fred' }
 
12959    * // The `_.property` iteratee shorthand.
 
12960    * _.map(users, 'user');
 
12961    * // => ['barney', 'fred']
 
12963   function map(collection, iteratee) {
 
12964     var func = isArray(collection) ? arrayMap : baseMap;
 
12965     return func(collection, getIteratee(iteratee, 3));
 
12969    * Reduces `collection` to a value which is the accumulated result of running
 
12970    * each element in `collection` thru `iteratee`, where each successive
 
12971    * invocation is supplied the return value of the previous. If `accumulator`
 
12972    * is not given, the first element of `collection` is used as the initial
 
12973    * value. The iteratee is invoked with four arguments:
 
12974    * (accumulator, value, index|key, collection).
 
12976    * Many lodash methods are guarded to work as iteratees for methods like
 
12977    * `_.reduce`, `_.reduceRight`, and `_.transform`.
 
12979    * The guarded methods are:
 
12980    * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
 
12986    * @category Collection
 
12987    * @param {Array|Object} collection The collection to iterate over.
 
12988    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
 
12989    * @param {*} [accumulator] The initial value.
 
12990    * @returns {*} Returns the accumulated value.
 
12991    * @see _.reduceRight
 
12994    * _.reduce([1, 2], function(sum, n) {
 
12999    * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
 
13000    *   (result[value] || (result[value] = [])).push(key);
 
13003    * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
 
13005   function reduce(collection, iteratee, accumulator) {
 
13006     var func = isArray(collection) ? arrayReduce : baseReduce,
 
13007         initAccum = arguments.length < 3;
 
13009     return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);
 
13013    * The opposite of `_.filter`; this method returns the elements of `collection`
 
13014    * that `predicate` does **not** return truthy for.
 
13019    * @category Collection
 
13020    * @param {Array|Object} collection The collection to iterate over.
 
13021    * @param {Array|Function|Object|string} [predicate=_.identity]
 
13022    *  The function invoked per iteration.
 
13023    * @returns {Array} Returns the new filtered array.
 
13028    *   { 'user': 'barney', 'age': 36, 'active': false },
 
13029    *   { 'user': 'fred',   'age': 40, 'active': true }
 
13032    * _.reject(users, function(o) { return !o.active; });
 
13033    * // => objects for ['fred']
 
13035    * // The `_.matches` iteratee shorthand.
 
13036    * _.reject(users, { 'age': 40, 'active': true });
 
13037    * // => objects for ['barney']
 
13039    * // The `_.matchesProperty` iteratee shorthand.
 
13040    * _.reject(users, ['active', false]);
 
13041    * // => objects for ['fred']
 
13043    * // The `_.property` iteratee shorthand.
 
13044    * _.reject(users, 'active');
 
13045    * // => objects for ['barney']
 
13047   function reject(collection, predicate) {
 
13048     var func = isArray(collection) ? arrayFilter : baseFilter;
 
13049     predicate = getIteratee(predicate, 3);
 
13050     return func(collection, function(value, index, collection) {
 
13051       return !predicate(value, index, collection);
 
13056    * Checks if `predicate` returns truthy for **any** element of `collection`.
 
13057    * Iteration is stopped once `predicate` returns truthy. The predicate is
 
13058    * invoked with three arguments: (value, index|key, collection).
 
13063    * @category Collection
 
13064    * @param {Array|Object} collection The collection to iterate over.
 
13065    * @param {Array|Function|Object|string} [predicate=_.identity]
 
13066    *  The function invoked per iteration.
 
13067    * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
 
13068    * @returns {boolean} Returns `true` if any element passes the predicate check,
 
13072    * _.some([null, 0, 'yes', false], Boolean);
 
13076    *   { 'user': 'barney', 'active': true },
 
13077    *   { 'user': 'fred',   'active': false }
 
13080    * // The `_.matches` iteratee shorthand.
 
13081    * _.some(users, { 'user': 'barney', 'active': false });
 
13084    * // The `_.matchesProperty` iteratee shorthand.
 
13085    * _.some(users, ['active', false]);
 
13088    * // The `_.property` iteratee shorthand.
 
13089    * _.some(users, 'active');
 
13092   function some(collection, predicate, guard) {
 
13093     var func = isArray(collection) ? arraySome : baseSome;
 
13094     if (guard && isIterateeCall(collection, predicate, guard)) {
 
13095       predicate = undefined;
 
13097     return func(collection, getIteratee(predicate, 3));
 
13100   /*------------------------------------------------------------------------*/
 
13103    * Gets the timestamp of the number of milliseconds that have elapsed since
 
13104    * the Unix epoch (1 January 1970 00:00:00 UTC).
 
13111    * @returns {number} Returns the timestamp.
 
13114    * _.defer(function(stamp) {
 
13115    *   console.log(_.now() - stamp);
 
13117    * // => Logs the number of milliseconds it took for the deferred function to be invoked.
 
13119   var now = Date.now;
 
13121   /*------------------------------------------------------------------------*/
 
13124    * Creates a function that invokes `func` with the `this` binding of `thisArg`
 
13125    * and `partials` prepended to the arguments it receives.
 
13127    * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
 
13128    * may be used as a placeholder for partially applied arguments.
 
13130    * **Note:** Unlike native `Function#bind` this method doesn't set the "length"
 
13131    * property of bound functions.
 
13136    * @category Function
 
13137    * @param {Function} func The function to bind.
 
13138    * @param {*} thisArg The `this` binding of `func`.
 
13139    * @param {...*} [partials] The arguments to be partially applied.
 
13140    * @returns {Function} Returns the new bound function.
 
13143    * var greet = function(greeting, punctuation) {
 
13144    *   return greeting + ' ' + this.user + punctuation;
 
13147    * var object = { 'user': 'fred' };
 
13149    * var bound = _.bind(greet, object, 'hi');
 
13153    * // Bound with placeholders.
 
13154    * var bound = _.bind(greet, object, _, '!');
 
13158   var bind = rest(function(func, thisArg, partials) {
 
13159     var bitmask = BIND_FLAG;
 
13160     if (partials.length) {
 
13161       var holders = replaceHolders(partials, getHolder(bind));
 
13162       bitmask |= PARTIAL_FLAG;
 
13164     return createWrapper(func, bitmask, thisArg, partials, holders);
 
13168    * Creates a debounced function that delays invoking `func` until after `wait`
 
13169    * milliseconds have elapsed since the last time the debounced function was
 
13170    * invoked. The debounced function comes with a `cancel` method to cancel
 
13171    * delayed `func` invocations and a `flush` method to immediately invoke them.
 
13172    * Provide an options object to indicate whether `func` should be invoked on
 
13173    * the leading and/or trailing edge of the `wait` timeout. The `func` is invoked
 
13174    * with the last arguments provided to the debounced function. Subsequent calls
 
13175    * to the debounced function return the result of the last `func` invocation.
 
13177    * **Note:** If `leading` and `trailing` options are `true`, `func` is invoked
 
13178    * on the trailing edge of the timeout only if the debounced function is
 
13179    * invoked more than once during the `wait` timeout.
 
13181    * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
 
13182    * for details over the differences between `_.debounce` and `_.throttle`.
 
13187    * @category Function
 
13188    * @param {Function} func The function to debounce.
 
13189    * @param {number} [wait=0] The number of milliseconds to delay.
 
13190    * @param {Object} [options={}] The options object.
 
13191    * @param {boolean} [options.leading=false]
 
13192    *  Specify invoking on the leading edge of the timeout.
 
13193    * @param {number} [options.maxWait]
 
13194    *  The maximum time `func` is allowed to be delayed before it's invoked.
 
13195    * @param {boolean} [options.trailing=true]
 
13196    *  Specify invoking on the trailing edge of the timeout.
 
13197    * @returns {Function} Returns the new debounced function.
 
13200    * // Avoid costly calculations while the window size is in flux.
 
13201    * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
 
13203    * // Invoke `sendMail` when clicked, debouncing subsequent calls.
 
13204    * jQuery(element).on('click', _.debounce(sendMail, 300, {
 
13206    *   'trailing': false
 
13209    * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
 
13210    * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
 
13211    * var source = new EventSource('/stream');
 
13212    * jQuery(source).on('message', debounced);
 
13214    * // Cancel the trailing debounced invocation.
 
13215    * jQuery(window).on('popstate', debounced.cancel);
 
13217   function debounce(func, wait, options) {
 
13224         lastInvokeTime = 0,
 
13229     if (typeof func != 'function') {
 
13230       throw new TypeError(FUNC_ERROR_TEXT);
 
13232     wait = toNumber(wait) || 0;
 
13233     if (isObject(options)) {
 
13234       leading = !!options.leading;
 
13235       maxing = 'maxWait' in options;
 
13236       maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
 
13237       trailing = 'trailing' in options ? !!options.trailing : trailing;
 
13240     function invokeFunc(time) {
 
13241       var args = lastArgs,
 
13242           thisArg = lastThis;
 
13244       lastArgs = lastThis = undefined;
 
13245       lastInvokeTime = time;
 
13246       result = func.apply(thisArg, args);
 
13250     function leadingEdge(time) {
 
13251       // Reset any `maxWait` timer.
 
13252       lastInvokeTime = time;
 
13253       // Start the timer for the trailing edge.
 
13254       timerId = setTimeout(timerExpired, wait);
 
13255       // Invoke the leading edge.
 
13256       return leading ? invokeFunc(time) : result;
 
13259     function remainingWait(time) {
 
13260       var timeSinceLastCall = time - lastCallTime,
 
13261           timeSinceLastInvoke = time - lastInvokeTime,
 
13262           result = wait - timeSinceLastCall;
 
13264       return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;
 
13267     function shouldInvoke(time) {
 
13268       var timeSinceLastCall = time - lastCallTime,
 
13269           timeSinceLastInvoke = time - lastInvokeTime;
 
13271       // Either this is the first call, activity has stopped and we're at the
 
13272       // trailing edge, the system time has gone backwards and we're treating
 
13273       // it as the trailing edge, or we've hit the `maxWait` limit.
 
13274       return (!lastCallTime || (timeSinceLastCall >= wait) ||
 
13275         (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
 
13278     function timerExpired() {
 
13280       if (shouldInvoke(time)) {
 
13281         return trailingEdge(time);
 
13283       // Restart the timer.
 
13284       timerId = setTimeout(timerExpired, remainingWait(time));
 
13287     function trailingEdge(time) {
 
13288       clearTimeout(timerId);
 
13289       timerId = undefined;
 
13291       // Only invoke if we have `lastArgs` which means `func` has been
 
13292       // debounced at least once.
 
13293       if (trailing && lastArgs) {
 
13294         return invokeFunc(time);
 
13296       lastArgs = lastThis = undefined;
 
13300     function cancel() {
 
13301       if (timerId !== undefined) {
 
13302         clearTimeout(timerId);
 
13304       lastCallTime = lastInvokeTime = 0;
 
13305       lastArgs = lastThis = timerId = undefined;
 
13309       return timerId === undefined ? result : trailingEdge(now());
 
13312     function debounced() {
 
13314           isInvoking = shouldInvoke(time);
 
13316       lastArgs = arguments;
 
13318       lastCallTime = time;
 
13321         if (timerId === undefined) {
 
13322           return leadingEdge(lastCallTime);
 
13325           // Handle invocations in a tight loop.
 
13326           clearTimeout(timerId);
 
13327           timerId = setTimeout(timerExpired, wait);
 
13328           return invokeFunc(lastCallTime);
 
13331       if (timerId === undefined) {
 
13332         timerId = setTimeout(timerExpired, wait);
 
13336     debounced.cancel = cancel;
 
13337     debounced.flush = flush;
 
13342    * Creates a function that memoizes the result of `func`. If `resolver` is
 
13343    * provided, it determines the cache key for storing the result based on the
 
13344    * arguments provided to the memoized function. By default, the first argument
 
13345    * provided to the memoized function is used as the map cache key. The `func`
 
13346    * is invoked with the `this` binding of the memoized function.
 
13348    * **Note:** The cache is exposed as the `cache` property on the memoized
 
13349    * function. Its creation may be customized by replacing the `_.memoize.Cache`
 
13350    * constructor with one whose instances implement the
 
13351    * [`Map`](http://ecma-international.org/ecma-262/6.0/#sec-properties-of-the-map-prototype-object)
 
13352    * method interface of `delete`, `get`, `has`, and `set`.
 
13357    * @category Function
 
13358    * @param {Function} func The function to have its output memoized.
 
13359    * @param {Function} [resolver] The function to resolve the cache key.
 
13360    * @returns {Function} Returns the new memoized function.
 
13363    * var object = { 'a': 1, 'b': 2 };
 
13364    * var other = { 'c': 3, 'd': 4 };
 
13366    * var values = _.memoize(_.values);
 
13377    * // Modify the result cache.
 
13378    * values.cache.set(object, ['a', 'b']);
 
13382    * // Replace `_.memoize.Cache`.
 
13383    * _.memoize.Cache = WeakMap;
 
13385   function memoize(func, resolver) {
 
13386     if (typeof func != 'function' || (resolver && typeof resolver != 'function')) {
 
13387       throw new TypeError(FUNC_ERROR_TEXT);
 
13389     var memoized = function() {
 
13390       var args = arguments,
 
13391           key = resolver ? resolver.apply(this, args) : args[0],
 
13392           cache = memoized.cache;
 
13394       if (cache.has(key)) {
 
13395         return cache.get(key);
 
13397       var result = func.apply(this, args);
 
13398       memoized.cache = cache.set(key, result);
 
13401     memoized.cache = new (memoize.Cache || MapCache);
 
13405   // Assign cache to `_.memoize`.
 
13406   memoize.Cache = MapCache;
 
13409    * Creates a function that invokes `func` with the `this` binding of the
 
13410    * created function and arguments from `start` and beyond provided as
 
13413    * **Note:** This method is based on the
 
13414    * [rest parameter](https://mdn.io/rest_parameters).
 
13419    * @category Function
 
13420    * @param {Function} func The function to apply a rest parameter to.
 
13421    * @param {number} [start=func.length-1] The start position of the rest parameter.
 
13422    * @returns {Function} Returns the new function.
 
13425    * var say = _.rest(function(what, names) {
 
13426    *   return what + ' ' + _.initial(names).join(', ') +
 
13427    *     (_.size(names) > 1 ? ', & ' : '') + _.last(names);
 
13430    * say('hello', 'fred', 'barney', 'pebbles');
 
13431    * // => 'hello fred, barney, & pebbles'
 
13433   function rest(func, start) {
 
13434     if (typeof func != 'function') {
 
13435       throw new TypeError(FUNC_ERROR_TEXT);
 
13437     start = nativeMax(start === undefined ? (func.length - 1) : toInteger(start), 0);
 
13438     return function() {
 
13439       var args = arguments,
 
13441           length = nativeMax(args.length - start, 0),
 
13442           array = Array(length);
 
13444       while (++index < length) {
 
13445         array[index] = args[start + index];
 
13448         case 0: return func.call(this, array);
 
13449         case 1: return func.call(this, args[0], array);
 
13450         case 2: return func.call(this, args[0], args[1], array);
 
13452       var otherArgs = Array(start + 1);
 
13454       while (++index < start) {
 
13455         otherArgs[index] = args[index];
 
13457       otherArgs[start] = array;
 
13458       return apply(func, this, otherArgs);
 
13463    * Creates a throttled function that only invokes `func` at most once per
 
13464    * every `wait` milliseconds. The throttled function comes with a `cancel`
 
13465    * method to cancel delayed `func` invocations and a `flush` method to
 
13466    * immediately invoke them. Provide an options object to indicate whether
 
13467    * `func` should be invoked on the leading and/or trailing edge of the `wait`
 
13468    * timeout. The `func` is invoked with the last arguments provided to the
 
13469    * throttled function. Subsequent calls to the throttled function return the
 
13470    * result of the last `func` invocation.
 
13472    * **Note:** If `leading` and `trailing` options are `true`, `func` is
 
13473    * invoked on the trailing edge of the timeout only if the throttled function
 
13474    * is invoked more than once during the `wait` timeout.
 
13476    * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
 
13477    * for details over the differences between `_.throttle` and `_.debounce`.
 
13482    * @category Function
 
13483    * @param {Function} func The function to throttle.
 
13484    * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
 
13485    * @param {Object} [options={}] The options object.
 
13486    * @param {boolean} [options.leading=true]
 
13487    *  Specify invoking on the leading edge of the timeout.
 
13488    * @param {boolean} [options.trailing=true]
 
13489    *  Specify invoking on the trailing edge of the timeout.
 
13490    * @returns {Function} Returns the new throttled function.
 
13493    * // Avoid excessively updating the position while scrolling.
 
13494    * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
 
13496    * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
 
13497    * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
 
13498    * jQuery(element).on('click', throttled);
 
13500    * // Cancel the trailing throttled invocation.
 
13501    * jQuery(window).on('popstate', throttled.cancel);
 
13503   function throttle(func, wait, options) {
 
13504     var leading = true,
 
13507     if (typeof func != 'function') {
 
13508       throw new TypeError(FUNC_ERROR_TEXT);
 
13510     if (isObject(options)) {
 
13511       leading = 'leading' in options ? !!options.leading : leading;
 
13512       trailing = 'trailing' in options ? !!options.trailing : trailing;
 
13514     return debounce(func, wait, {
 
13515       'leading': leading,
 
13517       'trailing': trailing
 
13521   /*------------------------------------------------------------------------*/
 
13524    * Creates a shallow clone of `value`.
 
13526    * **Note:** This method is loosely based on the
 
13527    * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)
 
13528    * and supports cloning arrays, array buffers, booleans, date objects, maps,
 
13529    * numbers, `Object` objects, regexes, sets, strings, symbols, and typed
 
13530    * arrays. The own enumerable properties of `arguments` objects are cloned
 
13531    * as plain objects. An empty object is returned for uncloneable values such
 
13532    * as error objects, functions, DOM nodes, and WeakMaps.
 
13538    * @param {*} value The value to clone.
 
13539    * @returns {*} Returns the cloned value.
 
13543    * var objects = [{ 'a': 1 }, { 'b': 2 }];
 
13545    * var shallow = _.clone(objects);
 
13546    * console.log(shallow[0] === objects[0]);
 
13549   function clone(value) {
 
13550     return baseClone(value, false, true);
 
13554    * This method is like `_.clone` except that it recursively clones `value`.
 
13560    * @param {*} value The value to recursively clone.
 
13561    * @returns {*} Returns the deep cloned value.
 
13565    * var objects = [{ 'a': 1 }, { 'b': 2 }];
 
13567    * var deep = _.cloneDeep(objects);
 
13568    * console.log(deep[0] === objects[0]);
 
13571   function cloneDeep(value) {
 
13572     return baseClone(value, true, true);
 
13577    * [`SameValueZero`](http://ecma-international.org/ecma-262/6.0/#sec-samevaluezero)
 
13578    * comparison between two values to determine if they are equivalent.
 
13584    * @param {*} value The value to compare.
 
13585    * @param {*} other The other value to compare.
 
13586    * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
 
13589    * var object = { 'user': 'fred' };
 
13590    * var other = { 'user': 'fred' };
 
13592    * _.eq(object, object);
 
13595    * _.eq(object, other);
 
13601    * _.eq('a', Object('a'));
 
13607   function eq(value, other) {
 
13608     return value === other || (value !== value && other !== other);
 
13612    * Checks if `value` is likely an `arguments` object.
 
13618    * @param {*} value The value to check.
 
13619    * @returns {boolean} Returns `true` if `value` is correctly classified,
 
13623    * _.isArguments(function() { return arguments; }());
 
13626    * _.isArguments([1, 2, 3]);
 
13629   function isArguments(value) {
 
13630     // Safari 8.1 incorrectly makes `arguments.callee` enumerable in strict mode.
 
13631     return isArrayLikeObject(value) && hasOwnProperty.call(value, 'callee') &&
 
13632       (!propertyIsEnumerable.call(value, 'callee') || objectToString.call(value) == argsTag);
 
13636    * Checks if `value` is classified as an `Array` object.
 
13643    * @param {*} value The value to check.
 
13644    * @returns {boolean} Returns `true` if `value` is correctly classified,
 
13648    * _.isArray([1, 2, 3]);
 
13651    * _.isArray(document.body.children);
 
13654    * _.isArray('abc');
 
13657    * _.isArray(_.noop);
 
13660   var isArray = Array.isArray;
 
13663    * Checks if `value` is array-like. A value is considered array-like if it's
 
13664    * not a function and has a `value.length` that's an integer greater than or
 
13665    * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
 
13671    * @param {*} value The value to check.
 
13672    * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
 
13675    * _.isArrayLike([1, 2, 3]);
 
13678    * _.isArrayLike(document.body.children);
 
13681    * _.isArrayLike('abc');
 
13684    * _.isArrayLike(_.noop);
 
13687   function isArrayLike(value) {
 
13688     return value != null && isLength(getLength(value)) && !isFunction(value);
 
13692    * This method is like `_.isArrayLike` except that it also checks if `value`
 
13699    * @param {*} value The value to check.
 
13700    * @returns {boolean} Returns `true` if `value` is an array-like object,
 
13704    * _.isArrayLikeObject([1, 2, 3]);
 
13707    * _.isArrayLikeObject(document.body.children);
 
13710    * _.isArrayLikeObject('abc');
 
13713    * _.isArrayLikeObject(_.noop);
 
13716   function isArrayLikeObject(value) {
 
13717     return isObjectLike(value) && isArrayLike(value);
 
13721    * Checks if `value` is a buffer.
 
13727    * @param {*} value The value to check.
 
13728    * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
 
13731    * _.isBuffer(new Buffer(2));
 
13734    * _.isBuffer(new Uint8Array(2));
 
13737   var isBuffer = !Buffer ? constant(false) : function(value) {
 
13738     return value instanceof Buffer;
 
13742    * Checks if `value` is an empty object, collection, map, or set.
 
13744    * Objects are considered empty if they have no own enumerable string keyed
 
13747    * Array-like values such as `arguments` objects, arrays, buffers, strings, or
 
13748    * jQuery-like collections are considered empty if they have a `length` of `0`.
 
13749    * Similarly, maps and sets are considered empty if they have a `size` of `0`.
 
13755    * @param {*} value The value to check.
 
13756    * @returns {boolean} Returns `true` if `value` is empty, else `false`.
 
13768    * _.isEmpty([1, 2, 3]);
 
13771    * _.isEmpty({ 'a': 1 });
 
13774   function isEmpty(value) {
 
13775     if (isArrayLike(value) &&
 
13776         (isArray(value) || isString(value) || isFunction(value.splice) ||
 
13777           isArguments(value) || isBuffer(value))) {
 
13778       return !value.length;
 
13780     if (isObjectLike(value)) {
 
13781       var tag = getTag(value);
 
13782       if (tag == mapTag || tag == setTag) {
 
13783         return !value.size;
 
13786     for (var key in value) {
 
13787       if (hasOwnProperty.call(value, key)) {
 
13791     return !(nonEnumShadows && keys(value).length);
 
13795    * Performs a deep comparison between two values to determine if they are
 
13798    * **Note:** This method supports comparing arrays, array buffers, booleans,
 
13799    * date objects, error objects, maps, numbers, `Object` objects, regexes,
 
13800    * sets, strings, symbols, and typed arrays. `Object` objects are compared
 
13801    * by their own, not inherited, enumerable properties. Functions and DOM
 
13802    * nodes are **not** supported.
 
13808    * @param {*} value The value to compare.
 
13809    * @param {*} other The other value to compare.
 
13810    * @returns {boolean} Returns `true` if the values are equivalent,
 
13814    * var object = { 'user': 'fred' };
 
13815    * var other = { 'user': 'fred' };
 
13817    * _.isEqual(object, other);
 
13820    * object === other;
 
13823   function isEqual(value, other) {
 
13824     return baseIsEqual(value, other);
 
13828    * Checks if `value` is classified as a `Function` object.
 
13834    * @param {*} value The value to check.
 
13835    * @returns {boolean} Returns `true` if `value` is correctly classified,
 
13842    * _.isFunction(/abc/);
 
13845   function isFunction(value) {
 
13846     // The use of `Object#toString` avoids issues with the `typeof` operator
 
13847     // in Safari 8 which returns 'object' for typed array and weak map constructors,
 
13848     // and PhantomJS 1.9 which returns 'function' for `NodeList` instances.
 
13849     var tag = isObject(value) ? objectToString.call(value) : '';
 
13850     return tag == funcTag || tag == genTag;
 
13854    * Checks if `value` is a valid array-like length.
 
13856    * **Note:** This function is loosely based on
 
13857    * [`ToLength`](http://ecma-international.org/ecma-262/6.0/#sec-tolength).
 
13863    * @param {*} value The value to check.
 
13864    * @returns {boolean} Returns `true` if `value` is a valid length,
 
13871    * _.isLength(Number.MIN_VALUE);
 
13874    * _.isLength(Infinity);
 
13880   function isLength(value) {
 
13881     return typeof value == 'number' &&
 
13882       value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
 
13886    * Checks if `value` is the
 
13887    * [language type](http://www.ecma-international.org/ecma-262/6.0/#sec-ecmascript-language-types)
 
13888    * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
 
13894    * @param {*} value The value to check.
 
13895    * @returns {boolean} Returns `true` if `value` is an object, else `false`.
 
13901    * _.isObject([1, 2, 3]);
 
13904    * _.isObject(_.noop);
 
13907    * _.isObject(null);
 
13910   function isObject(value) {
 
13911     var type = typeof value;
 
13912     return !!value && (type == 'object' || type == 'function');
 
13916    * Checks if `value` is object-like. A value is object-like if it's not `null`
 
13917    * and has a `typeof` result of "object".
 
13923    * @param {*} value The value to check.
 
13924    * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
 
13927    * _.isObjectLike({});
 
13930    * _.isObjectLike([1, 2, 3]);
 
13933    * _.isObjectLike(_.noop);
 
13936    * _.isObjectLike(null);
 
13939   function isObjectLike(value) {
 
13940     return !!value && typeof value == 'object';
 
13944    * Checks if `value` is a native function.
 
13950    * @param {*} value The value to check.
 
13951    * @returns {boolean} Returns `true` if `value` is a native function,
 
13955    * _.isNative(Array.prototype.push);
 
13961   function isNative(value) {
 
13962     if (!isObject(value)) {
 
13965     var pattern = (isFunction(value) || isHostObject(value)) ? reIsNative : reIsHostCtor;
 
13966     return pattern.test(toSource(value));
 
13970    * Checks if `value` is a plain object, that is, an object created by the
 
13971    * `Object` constructor or one with a `[[Prototype]]` of `null`.
 
13977    * @param {*} value The value to check.
 
13978    * @returns {boolean} Returns `true` if `value` is a plain object,
 
13986    * _.isPlainObject(new Foo);
 
13989    * _.isPlainObject([1, 2, 3]);
 
13992    * _.isPlainObject({ 'x': 0, 'y': 0 });
 
13995    * _.isPlainObject(Object.create(null));
 
13998   function isPlainObject(value) {
 
13999     if (!isObjectLike(value) ||
 
14000         objectToString.call(value) != objectTag || isHostObject(value)) {
 
14003     var proto = getPrototype(value);
 
14004     if (proto === null) {
 
14007     var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
 
14008     return (typeof Ctor == 'function' &&
 
14009       Ctor instanceof Ctor && funcToString.call(Ctor) == objectCtorString);
 
14013    * Checks if `value` is classified as a `String` primitive or object.
 
14019    * @param {*} value The value to check.
 
14020    * @returns {boolean} Returns `true` if `value` is correctly classified,
 
14024    * _.isString('abc');
 
14030   function isString(value) {
 
14031     return typeof value == 'string' ||
 
14032       (!isArray(value) && isObjectLike(value) && objectToString.call(value) == stringTag);
 
14036    * Checks if `value` is classified as a `Symbol` primitive or object.
 
14042    * @param {*} value The value to check.
 
14043    * @returns {boolean} Returns `true` if `value` is correctly classified,
 
14047    * _.isSymbol(Symbol.iterator);
 
14050    * _.isSymbol('abc');
 
14053   function isSymbol(value) {
 
14054     return typeof value == 'symbol' ||
 
14055       (isObjectLike(value) && objectToString.call(value) == symbolTag);
 
14059    * Checks if `value` is classified as a typed array.
 
14065    * @param {*} value The value to check.
 
14066    * @returns {boolean} Returns `true` if `value` is correctly classified,
 
14070    * _.isTypedArray(new Uint8Array);
 
14073    * _.isTypedArray([]);
 
14076   function isTypedArray(value) {
 
14077     return isObjectLike(value) &&
 
14078       isLength(value.length) && !!typedArrayTags[objectToString.call(value)];
 
14082    * Converts `value` to an array.
 
14088    * @param {*} value The value to convert.
 
14089    * @returns {Array} Returns the converted array.
 
14092    * _.toArray({ 'a': 1, 'b': 2 });
 
14095    * _.toArray('abc');
 
14096    * // => ['a', 'b', 'c']
 
14104   function toArray(value) {
 
14108     if (isArrayLike(value)) {
 
14109       return isString(value) ? stringToArray(value) : copyArray(value);
 
14111     if (iteratorSymbol && value[iteratorSymbol]) {
 
14112       return iteratorToArray(value[iteratorSymbol]());
 
14114     var tag = getTag(value),
 
14115         func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);
 
14117     return func(value);
 
14121    * Converts `value` to a finite number.
 
14127    * @param {*} value The value to convert.
 
14128    * @returns {number} Returns the converted number.
 
14134    * _.toFinite(Number.MIN_VALUE);
 
14137    * _.toFinite(Infinity);
 
14138    * // => 1.7976931348623157e+308
 
14140    * _.toFinite('3.2');
 
14143   function toFinite(value) {
 
14145       return value === 0 ? value : 0;
 
14147     value = toNumber(value);
 
14148     if (value === INFINITY || value === -INFINITY) {
 
14149       var sign = (value < 0 ? -1 : 1);
 
14150       return sign * MAX_INTEGER;
 
14152     return value === value ? value : 0;
 
14156    * Converts `value` to an integer.
 
14158    * **Note:** This function is loosely based on
 
14159    * [`ToInteger`](http://www.ecma-international.org/ecma-262/6.0/#sec-tointeger).
 
14165    * @param {*} value The value to convert.
 
14166    * @returns {number} Returns the converted integer.
 
14169    * _.toInteger(3.2);
 
14172    * _.toInteger(Number.MIN_VALUE);
 
14175    * _.toInteger(Infinity);
 
14176    * // => 1.7976931348623157e+308
 
14178    * _.toInteger('3.2');
 
14181   function toInteger(value) {
 
14182     var result = toFinite(value),
 
14183         remainder = result % 1;
 
14185     return result === result ? (remainder ? result - remainder : result) : 0;
 
14189    * Converts `value` to a number.
 
14195    * @param {*} value The value to process.
 
14196    * @returns {number} Returns the number.
 
14202    * _.toNumber(Number.MIN_VALUE);
 
14205    * _.toNumber(Infinity);
 
14208    * _.toNumber('3.2');
 
14211   function toNumber(value) {
 
14212     if (typeof value == 'number') {
 
14215     if (isSymbol(value)) {
 
14218     if (isObject(value)) {
 
14219       var other = isFunction(value.valueOf) ? value.valueOf() : value;
 
14220       value = isObject(other) ? (other + '') : other;
 
14222     if (typeof value != 'string') {
 
14223       return value === 0 ? value : +value;
 
14225     value = value.replace(reTrim, '');
 
14226     var isBinary = reIsBinary.test(value);
 
14227     return (isBinary || reIsOctal.test(value))
 
14228       ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
 
14229       : (reIsBadHex.test(value) ? NAN : +value);
 
14233    * Converts `value` to a plain object flattening inherited enumerable string
 
14234    * keyed properties of `value` to own properties of the plain object.
 
14240    * @param {*} value The value to convert.
 
14241    * @returns {Object} Returns the converted plain object.
 
14248    * Foo.prototype.c = 3;
 
14250    * _.assign({ 'a': 1 }, new Foo);
 
14251    * // => { 'a': 1, 'b': 2 }
 
14253    * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
 
14254    * // => { 'a': 1, 'b': 2, 'c': 3 }
 
14256   function toPlainObject(value) {
 
14257     return copyObject(value, keysIn(value));
 
14261    * Converts `value` to a string. An empty string is returned for `null`
 
14262    * and `undefined` values. The sign of `-0` is preserved.
 
14268    * @param {*} value The value to process.
 
14269    * @returns {string} Returns the string.
 
14272    * _.toString(null);
 
14278    * _.toString([1, 2, 3]);
 
14281   function toString(value) {
 
14282     return value == null ? '' : baseToString(value);
 
14285   /*------------------------------------------------------------------------*/
 
14288    * Assigns own enumerable string keyed properties of source objects to the
 
14289    * destination object. Source objects are applied from left to right.
 
14290    * Subsequent sources overwrite property assignments of previous sources.
 
14292    * **Note:** This method mutates `object` and is loosely based on
 
14293    * [`Object.assign`](https://mdn.io/Object/assign).
 
14299    * @param {Object} object The destination object.
 
14300    * @param {...Object} [sources] The source objects.
 
14301    * @returns {Object} Returns `object`.
 
14313    * Foo.prototype.d = 4;
 
14314    * Bar.prototype.f = 6;
 
14316    * _.assign({ 'a': 1 }, new Foo, new Bar);
 
14317    * // => { 'a': 1, 'c': 3, 'e': 5 }
 
14319   var assign = createAssigner(function(object, source) {
 
14320     if (nonEnumShadows || isPrototype(source) || isArrayLike(source)) {
 
14321       copyObject(source, keys(source), object);
 
14324     for (var key in source) {
 
14325       if (hasOwnProperty.call(source, key)) {
 
14326         assignValue(object, key, source[key]);
 
14332    * This method is like `_.assign` except that it iterates over own and
 
14333    * inherited source properties.
 
14335    * **Note:** This method mutates `object`.
 
14342    * @param {Object} object The destination object.
 
14343    * @param {...Object} [sources] The source objects.
 
14344    * @returns {Object} Returns `object`.
 
14356    * Foo.prototype.c = 3;
 
14357    * Bar.prototype.e = 5;
 
14359    * _.assignIn({ 'a': 1 }, new Foo, new Bar);
 
14360    * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4, 'e': 5 }
 
14362   var assignIn = createAssigner(function(object, source) {
 
14363     if (nonEnumShadows || isPrototype(source) || isArrayLike(source)) {
 
14364       copyObject(source, keysIn(source), object);
 
14367     for (var key in source) {
 
14368       assignValue(object, key, source[key]);
 
14373    * Iterates over own enumerable string keyed properties of an object and
 
14374    * invokes `iteratee` for each property. The iteratee is invoked with three
 
14375    * arguments: (value, key, object). Iteratee functions may exit iteration
 
14376    * early by explicitly returning `false`.
 
14382    * @param {Object} object The object to iterate over.
 
14383    * @param {Function} [iteratee=_.identity] The function invoked per iteration.
 
14384    * @returns {Object} Returns `object`.
 
14385    * @see _.forOwnRight
 
14393    * Foo.prototype.c = 3;
 
14395    * _.forOwn(new Foo, function(value, key) {
 
14396    *   console.log(key);
 
14398    * // => Logs 'a' then 'b' (iteration order is not guaranteed).
 
14400   function forOwn(object, iteratee) {
 
14401     return object && baseForOwn(object, getIteratee(iteratee, 3));
 
14405    * Gets the value at `path` of `object`. If the resolved value is
 
14406    * `undefined`, the `defaultValue` is used in its place.
 
14412    * @param {Object} object The object to query.
 
14413    * @param {Array|string} path The path of the property to get.
 
14414    * @param {*} [defaultValue] The value returned for `undefined` resolved values.
 
14415    * @returns {*} Returns the resolved value.
 
14418    * var object = { 'a': [{ 'b': { 'c': 3 } }] };
 
14420    * _.get(object, 'a[0].b.c');
 
14423    * _.get(object, ['a', '0', 'b', 'c']);
 
14426    * _.get(object, 'a.b.c', 'default');
 
14429   function get(object, path, defaultValue) {
 
14430     var result = object == null ? undefined : baseGet(object, path);
 
14431     return result === undefined ? defaultValue : result;
 
14435    * Checks if `path` is a direct or inherited property of `object`.
 
14441    * @param {Object} object The object to query.
 
14442    * @param {Array|string} path The path to check.
 
14443    * @returns {boolean} Returns `true` if `path` exists, else `false`.
 
14446    * var object = _.create({ 'a': _.create({ 'b': 2 }) });
 
14448    * _.hasIn(object, 'a');
 
14451    * _.hasIn(object, 'a.b');
 
14454    * _.hasIn(object, ['a', 'b']);
 
14457    * _.hasIn(object, 'b');
 
14460   function hasIn(object, path) {
 
14461     return object != null && hasPath(object, path, baseHasIn);
 
14465    * Creates an array of the own enumerable property names of `object`.
 
14467    * **Note:** Non-object values are coerced to objects. See the
 
14468    * [ES spec](http://ecma-international.org/ecma-262/6.0/#sec-object.keys)
 
14469    * for more details.
 
14475    * @param {Object} object The object to query.
 
14476    * @returns {Array} Returns the array of property names.
 
14484    * Foo.prototype.c = 3;
 
14487    * // => ['a', 'b'] (iteration order is not guaranteed)
 
14492   function keys(object) {
 
14493     var isProto = isPrototype(object);
 
14494     if (!(isProto || isArrayLike(object))) {
 
14495       return baseKeys(object);
 
14497     var indexes = indexKeys(object),
 
14498         skipIndexes = !!indexes,
 
14499         result = indexes || [],
 
14500         length = result.length;
 
14502     for (var key in object) {
 
14503       if (baseHas(object, key) &&
 
14504           !(skipIndexes && (key == 'length' || isIndex(key, length))) &&
 
14505           !(isProto && key == 'constructor')) {
 
14513    * Creates an array of the own and inherited enumerable property names of `object`.
 
14515    * **Note:** Non-object values are coerced to objects.
 
14521    * @param {Object} object The object to query.
 
14522    * @returns {Array} Returns the array of property names.
 
14530    * Foo.prototype.c = 3;
 
14532    * _.keysIn(new Foo);
 
14533    * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
 
14535   function keysIn(object) {
 
14537         isProto = isPrototype(object),
 
14538         props = baseKeysIn(object),
 
14539         propsLength = props.length,
 
14540         indexes = indexKeys(object),
 
14541         skipIndexes = !!indexes,
 
14542         result = indexes || [],
 
14543         length = result.length;
 
14545     while (++index < propsLength) {
 
14546       var key = props[index];
 
14547       if (!(skipIndexes && (key == 'length' || isIndex(key, length))) &&
 
14548           !(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
 
14556    * This method is like `_.assign` except that it recursively merges own and
 
14557    * inherited enumerable string keyed properties of source objects into the
 
14558    * destination object. Source properties that resolve to `undefined` are
 
14559    * skipped if a destination value exists. Array and plain object properties
 
14560    * are merged recursively. Other objects and value types are overridden by
 
14561    * assignment. Source objects are applied from left to right. Subsequent
 
14562    * sources overwrite property assignments of previous sources.
 
14564    * **Note:** This method mutates `object`.
 
14570    * @param {Object} object The destination object.
 
14571    * @param {...Object} [sources] The source objects.
 
14572    * @returns {Object} Returns `object`.
 
14576    *   'data': [{ 'user': 'barney' }, { 'user': 'fred' }]
 
14580    *   'data': [{ 'age': 36 }, { 'age': 40 }]
 
14583    * _.merge(users, ages);
 
14584    * // => { 'data': [{ 'user': 'barney', 'age': 36 }, { 'user': 'fred', 'age': 40 }] }
 
14586   var merge = createAssigner(function(object, source, srcIndex) {
 
14587     baseMerge(object, source, srcIndex);
 
14591    * The opposite of `_.pick`; this method creates an object composed of the
 
14592    * own and inherited enumerable string keyed properties of `object` that are
 
14599    * @param {Object} object The source object.
 
14600    * @param {...(string|string[])} [props] The property identifiers to omit.
 
14601    * @returns {Object} Returns the new object.
 
14604    * var object = { 'a': 1, 'b': '2', 'c': 3 };
 
14606    * _.omit(object, ['a', 'c']);
 
14607    * // => { 'b': '2' }
 
14609   var omit = rest(function(object, props) {
 
14610     if (object == null) {
 
14613     props = arrayMap(baseFlatten(props, 1), toKey);
 
14614     return basePick(object, baseDifference(getAllKeysIn(object), props));
 
14618    * Creates an object composed of the picked `object` properties.
 
14624    * @param {Object} object The source object.
 
14625    * @param {...(string|string[])} [props] The property identifiers to pick.
 
14626    * @returns {Object} Returns the new object.
 
14629    * var object = { 'a': 1, 'b': '2', 'c': 3 };
 
14631    * _.pick(object, ['a', 'c']);
 
14632    * // => { 'a': 1, 'c': 3 }
 
14634   var pick = rest(function(object, props) {
 
14635     return object == null ? {} : basePick(object, arrayMap(baseFlatten(props, 1), toKey));
 
14639    * Creates an array of own enumerable string keyed-value pairs for `object`
 
14640    * which can be consumed by `_.fromPairs`. If `object` is a map or set, its
 
14641    * entries are returned.
 
14648    * @param {Object} object The object to query.
 
14649    * @returns {Array} Returns the key-value pairs.
 
14657    * Foo.prototype.c = 3;
 
14659    * _.toPairs(new Foo);
 
14660    * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)
 
14662   var toPairs = createToPairs(keys);
 
14665    * Creates an array of the own enumerable string keyed property values of `object`.
 
14667    * **Note:** Non-object values are coerced to objects.
 
14673    * @param {Object} object The object to query.
 
14674    * @returns {Array} Returns the array of property values.
 
14682    * Foo.prototype.c = 3;
 
14684    * _.values(new Foo);
 
14685    * // => [1, 2] (iteration order is not guaranteed)
 
14690   function values(object) {
 
14691     return object ? baseValues(object, keys(object)) : [];
 
14694   /*------------------------------------------------------------------------*/
 
14697    * Creates a function that returns `value`.
 
14703    * @param {*} value The value to return from the new function.
 
14704    * @returns {Function} Returns the new constant function.
 
14707    * var object = { 'user': 'fred' };
 
14708    * var getter = _.constant(object);
 
14710    * getter() === object;
 
14713   function constant(value) {
 
14714     return function() {
 
14720    * This method returns the first argument given to it.
 
14726    * @param {*} value Any value.
 
14727    * @returns {*} Returns `value`.
 
14730    * var object = { 'user': 'fred' };
 
14732    * _.identity(object) === object;
 
14735   function identity(value) {
 
14740    * Creates a function that invokes `func` with the arguments of the created
 
14741    * function. If `func` is a property name, the created function returns the
 
14742    * property value for a given element. If `func` is an array or object, the
 
14743    * created function returns `true` for elements that contain the equivalent
 
14744    * source properties, otherwise it returns `false`.
 
14750    * @param {*} [func=_.identity] The value to convert to a callback.
 
14751    * @returns {Function} Returns the callback.
 
14755    *   { 'user': 'barney', 'age': 36, 'active': true },
 
14756    *   { 'user': 'fred',   'age': 40, 'active': false }
 
14759    * // The `_.matches` iteratee shorthand.
 
14760    * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));
 
14761    * // => [{ 'user': 'barney', 'age': 36, 'active': true }]
 
14763    * // The `_.matchesProperty` iteratee shorthand.
 
14764    * _.filter(users, _.iteratee(['user', 'fred']));
 
14765    * // => [{ 'user': 'fred', 'age': 40 }]
 
14767    * // The `_.property` iteratee shorthand.
 
14768    * _.map(users, _.iteratee('user'));
 
14769    * // => ['barney', 'fred']
 
14771    * // Create custom iteratee shorthands.
 
14772    * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {
 
14773    *   return !_.isRegExp(func) ? iteratee(func) : function(string) {
 
14774    *     return func.test(string);
 
14778    * _.filter(['abc', 'def'], /ef/);
 
14781   function iteratee(func) {
 
14782     return baseIteratee(typeof func == 'function' ? func : baseClone(func, true));
 
14786    * Adds all own enumerable string keyed function properties of a source
 
14787    * object to the destination object. If `object` is a function, then methods
 
14788    * are added to its prototype as well.
 
14790    * **Note:** Use `_.runInContext` to create a pristine `lodash` function to
 
14791    * avoid conflicts caused by modifying the original.
 
14797    * @param {Function|Object} [object=lodash] The destination object.
 
14798    * @param {Object} source The object of functions to add.
 
14799    * @param {Object} [options={}] The options object.
 
14800    * @param {boolean} [options.chain=true] Specify whether mixins are chainable.
 
14801    * @returns {Function|Object} Returns `object`.
 
14804    * function vowels(string) {
 
14805    *   return _.filter(string, function(v) {
 
14806    *     return /[aeiou]/i.test(v);
 
14810    * _.mixin({ 'vowels': vowels });
 
14811    * _.vowels('fred');
 
14814    * _('fred').vowels().value();
 
14817    * _.mixin({ 'vowels': vowels }, { 'chain': false });
 
14818    * _('fred').vowels();
 
14821   function mixin(object, source, options) {
 
14822     var props = keys(source),
 
14823         methodNames = baseFunctions(source, props);
 
14825     if (options == null &&
 
14826         !(isObject(source) && (methodNames.length || !props.length))) {
 
14830       methodNames = baseFunctions(source, keys(source));
 
14832     var chain = !(isObject(options) && 'chain' in options) || !!options.chain,
 
14833         isFunc = isFunction(object);
 
14835     arrayEach(methodNames, function(methodName) {
 
14836       var func = source[methodName];
 
14837       object[methodName] = func;
 
14839         object.prototype[methodName] = function() {
 
14840           var chainAll = this.__chain__;
 
14841           if (chain || chainAll) {
 
14842             var result = object(this.__wrapped__),
 
14843                 actions = result.__actions__ = copyArray(this.__actions__);
 
14845             actions.push({ 'func': func, 'args': arguments, 'thisArg': object });
 
14846             result.__chain__ = chainAll;
 
14849           return func.apply(object, arrayPush([this.value()], arguments));
 
14858    * A no-operation function that returns `undefined` regardless of the
 
14859    * arguments it receives.
 
14867    * var object = { 'user': 'fred' };
 
14869    * _.noop(object) === undefined;
 
14873     // No operation performed.
 
14877    * Creates a function that returns the value at `path` of a given object.
 
14883    * @param {Array|string} path The path of the property to get.
 
14884    * @returns {Function} Returns the new accessor function.
 
14888    *   { 'a': { 'b': 2 } },
 
14889    *   { 'a': { 'b': 1 } }
 
14892    * _.map(objects, _.property('a.b'));
 
14895    * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
 
14898   function property(path) {
 
14899     return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
 
14902   /*------------------------------------------------------------------------*/
 
14904   // Add methods that return wrapped values in chain sequences.
 
14905   lodash.assign = assign;
 
14906   lodash.assignIn = assignIn;
 
14907   lodash.bind = bind;
 
14908   lodash.chain = chain;
 
14909   lodash.chunk = chunk;
 
14910   lodash.compact = compact;
 
14911   lodash.constant = constant;
 
14912   lodash.debounce = debounce;
 
14913   lodash.difference = difference;
 
14914   lodash.filter = filter;
 
14915   lodash.flatten = flatten;
 
14916   lodash.groupBy = groupBy;
 
14917   lodash.intersection = intersection;
 
14918   lodash.iteratee = iteratee;
 
14919   lodash.keys = keys;
 
14920   lodash.keysIn = keysIn;
 
14922   lodash.memoize = memoize;
 
14923   lodash.merge = merge;
 
14924   lodash.mixin = mixin;
 
14925   lodash.omit = omit;
 
14926   lodash.pick = pick;
 
14927   lodash.property = property;
 
14928   lodash.reject = reject;
 
14929   lodash.rest = rest;
 
14930   lodash.reverse = reverse;
 
14932   lodash.throttle = throttle;
 
14933   lodash.thru = thru;
 
14934   lodash.toArray = toArray;
 
14935   lodash.toPairs = toPairs;
 
14936   lodash.toPlainObject = toPlainObject;
 
14937   lodash.union = union;
 
14938   lodash.uniq = uniq;
 
14939   lodash.values = values;
 
14940   lodash.without = without;
 
14943   lodash.entries = toPairs;
 
14944   lodash.extend = assignIn;
 
14946   // Add methods to `lodash.prototype`.
 
14947   mixin(lodash, lodash);
 
14949   /*------------------------------------------------------------------------*/
 
14951   // Add methods that return unwrapped values in chain sequences.
 
14952   lodash.clone = clone;
 
14953   lodash.cloneDeep = cloneDeep;
 
14955   lodash.every = every;
 
14956   lodash.find = find;
 
14957   lodash.forEach = forEach;
 
14958   lodash.forOwn = forOwn;
 
14960   lodash.hasIn = hasIn;
 
14961   lodash.head = head;
 
14962   lodash.identity = identity;
 
14963   lodash.includes = includes;
 
14964   lodash.indexOf = indexOf;
 
14965   lodash.isArguments = isArguments;
 
14966   lodash.isArray = isArray;
 
14967   lodash.isArrayLike = isArrayLike;
 
14968   lodash.isArrayLikeObject = isArrayLikeObject;
 
14969   lodash.isBuffer = isBuffer;
 
14970   lodash.isEmpty = isEmpty;
 
14971   lodash.isEqual = isEqual;
 
14972   lodash.isFunction = isFunction;
 
14973   lodash.isLength = isLength;
 
14974   lodash.isNative = isNative;
 
14975   lodash.isObject = isObject;
 
14976   lodash.isObjectLike = isObjectLike;
 
14977   lodash.isPlainObject = isPlainObject;
 
14978   lodash.isString = isString;
 
14979   lodash.isSymbol = isSymbol;
 
14980   lodash.isTypedArray = isTypedArray;
 
14981   lodash.last = last;
 
14982   lodash.noop = noop;
 
14984   lodash.reduce = reduce;
 
14985   lodash.some = some;
 
14986   lodash.toFinite = toFinite;
 
14987   lodash.toInteger = toInteger;
 
14988   lodash.toNumber = toNumber;
 
14989   lodash.toString = toString;
 
14992   lodash.each = forEach;
 
14993   lodash.first = head;
 
14995   mixin(lodash, (function() {
 
14997     baseForOwn(lodash, function(func, methodName) {
 
14998       if (!hasOwnProperty.call(lodash.prototype, methodName)) {
 
14999         source[methodName] = func;
 
15003   }()), { 'chain': false });
 
15005   /*------------------------------------------------------------------------*/
 
15008    * The semantic version number.
 
15014   lodash.VERSION = VERSION;
 
15016   // Assign default placeholders.
 
15017   bind.placeholder = lodash;
 
15019   // Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
 
15020   arrayEach(['drop', 'take'], function(methodName, index) {
 
15021     LazyWrapper.prototype[methodName] = function(n) {
 
15022       var filtered = this.__filtered__;
 
15023       if (filtered && !index) {
 
15024         return new LazyWrapper(this);
 
15026       n = n === undefined ? 1 : nativeMax(toInteger(n), 0);
 
15028       var result = this.clone();
 
15030         result.__takeCount__ = nativeMin(n, result.__takeCount__);
 
15032         result.__views__.push({
 
15033           'size': nativeMin(n, MAX_ARRAY_LENGTH),
 
15034           'type': methodName + (result.__dir__ < 0 ? 'Right' : '')
 
15040     LazyWrapper.prototype[methodName + 'Right'] = function(n) {
 
15041       return this.reverse()[methodName](n).reverse();
 
15045   // Add `LazyWrapper` methods that accept an `iteratee` value.
 
15046   arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {
 
15047     var type = index + 1,
 
15048         isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
 
15050     LazyWrapper.prototype[methodName] = function(iteratee) {
 
15051       var result = this.clone();
 
15052       result.__iteratees__.push({
 
15053         'iteratee': getIteratee(iteratee, 3),
 
15056       result.__filtered__ = result.__filtered__ || isFilter;
 
15061   // Add `LazyWrapper` methods for `_.head` and `_.last`.
 
15062   arrayEach(['head', 'last'], function(methodName, index) {
 
15063     var takeName = 'take' + (index ? 'Right' : '');
 
15065     LazyWrapper.prototype[methodName] = function() {
 
15066       return this[takeName](1).value()[0];
 
15070   // Add `LazyWrapper` methods for `_.initial` and `_.tail`.
 
15071   arrayEach(['initial', 'tail'], function(methodName, index) {
 
15072     var dropName = 'drop' + (index ? '' : 'Right');
 
15074     LazyWrapper.prototype[methodName] = function() {
 
15075       return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
 
15079   LazyWrapper.prototype.compact = function() {
 
15080     return this.filter(identity);
 
15083   LazyWrapper.prototype.find = function(predicate) {
 
15084     return this.filter(predicate).head();
 
15087   LazyWrapper.prototype.findLast = function(predicate) {
 
15088     return this.reverse().find(predicate);
 
15091   LazyWrapper.prototype.invokeMap = rest(function(path, args) {
 
15092     if (typeof path == 'function') {
 
15093       return new LazyWrapper(this);
 
15095     return this.map(function(value) {
 
15096       return baseInvoke(value, path, args);
 
15100   LazyWrapper.prototype.reject = function(predicate) {
 
15101     predicate = getIteratee(predicate, 3);
 
15102     return this.filter(function(value) {
 
15103       return !predicate(value);
 
15107   LazyWrapper.prototype.slice = function(start, end) {
 
15108     start = toInteger(start);
 
15111     if (result.__filtered__ && (start > 0 || end < 0)) {
 
15112       return new LazyWrapper(result);
 
15115       result = result.takeRight(-start);
 
15116     } else if (start) {
 
15117       result = result.drop(start);
 
15119     if (end !== undefined) {
 
15120       end = toInteger(end);
 
15121       result = end < 0 ? result.dropRight(-end) : result.take(end - start);
 
15126   LazyWrapper.prototype.takeRightWhile = function(predicate) {
 
15127     return this.reverse().takeWhile(predicate).reverse();
 
15130   LazyWrapper.prototype.toArray = function() {
 
15131     return this.take(MAX_ARRAY_LENGTH);
 
15134   // Add `LazyWrapper` methods to `lodash.prototype`.
 
15135   baseForOwn(LazyWrapper.prototype, function(func, methodName) {
 
15136     var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),
 
15137         isTaker = /^(?:head|last)$/.test(methodName),
 
15138         lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName],
 
15139         retUnwrapped = isTaker || /^find/.test(methodName);
 
15144     lodash.prototype[methodName] = function() {
 
15145       var value = this.__wrapped__,
 
15146           args = isTaker ? [1] : arguments,
 
15147           isLazy = value instanceof LazyWrapper,
 
15148           iteratee = args[0],
 
15149           useLazy = isLazy || isArray(value);
 
15151       var interceptor = function(value) {
 
15152         var result = lodashFunc.apply(lodash, arrayPush([value], args));
 
15153         return (isTaker && chainAll) ? result[0] : result;
 
15156       if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
 
15157         // Avoid lazy use if the iteratee has a "length" value other than `1`.
 
15158         isLazy = useLazy = false;
 
15160       var chainAll = this.__chain__,
 
15161           isHybrid = !!this.__actions__.length,
 
15162           isUnwrapped = retUnwrapped && !chainAll,
 
15163           onlyLazy = isLazy && !isHybrid;
 
15165       if (!retUnwrapped && useLazy) {
 
15166         value = onlyLazy ? value : new LazyWrapper(this);
 
15167         var result = func.apply(value, args);
 
15168         result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });
 
15169         return new LodashWrapper(result, chainAll);
 
15171       if (isUnwrapped && onlyLazy) {
 
15172         return func.apply(this, args);
 
15174       result = this.thru(interceptor);
 
15175       return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result;
 
15179   // Add `Array` methods to `lodash.prototype`.
 
15180   arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
 
15181     var func = arrayProto[methodName],
 
15182         chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
 
15183         retUnwrapped = /^(?:pop|shift)$/.test(methodName);
 
15185     lodash.prototype[methodName] = function() {
 
15186       var args = arguments;
 
15187       if (retUnwrapped && !this.__chain__) {
 
15188         var value = this.value();
 
15189         return func.apply(isArray(value) ? value : [], args);
 
15191       return this[chainName](function(value) {
 
15192         return func.apply(isArray(value) ? value : [], args);
 
15197   // Map minified method names to their real names.
 
15198   baseForOwn(LazyWrapper.prototype, function(func, methodName) {
 
15199     var lodashFunc = lodash[methodName];
 
15201       var key = (lodashFunc.name + ''),
 
15202           names = realNames[key] || (realNames[key] = []);
 
15204       names.push({ 'name': methodName, 'func': lodashFunc });
 
15208   realNames[createHybridWrapper(undefined, BIND_KEY_FLAG).name] = [{
 
15213   // Add methods to `LazyWrapper`.
 
15214   LazyWrapper.prototype.clone = lazyClone;
 
15215   LazyWrapper.prototype.reverse = lazyReverse;
 
15216   LazyWrapper.prototype.value = lazyValue;
 
15218   // Add chain sequence methods to the `lodash` wrapper.
 
15219   lodash.prototype.chain = wrapperChain;
 
15220   lodash.prototype.commit = wrapperCommit;
 
15221   lodash.prototype.next = wrapperNext;
 
15222   lodash.prototype.plant = wrapperPlant;
 
15223   lodash.prototype.reverse = wrapperReverse;
 
15224   lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
 
15226   if (iteratorSymbol) {
 
15227     lodash.prototype[iteratorSymbol] = wrapperToIterator;
 
15230   /*--------------------------------------------------------------------------*/
 
15232   // Expose Lodash on the free variable `window` or `self` when available so it's
 
15233   // globally accessible, even when bundled with Browserify, Webpack, etc. This
 
15234   // also prevents errors in cases where Lodash is loaded by a script tag in the
 
15235   // presence of an AMD loader. See http://requirejs.org/docs/errors.html#mismatch
 
15236   // for more details. Use `_.noConflict` to remove Lodash from the global object.
 
15237   (freeWindow || freeSelf || {})._ = lodash;
 
15239   if (freeExports && freeModule) {
 
15240     // Export for Node.js.
 
15241     if (moduleExports) {
 
15242       (freeModule.exports = lodash)._ = lodash;
 
15244     // Export for CommonJS support.
 
15245     freeExports._ = lodash;
 
15248     // Export to the global object.
 
15252 (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;
 
15253 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){
 
15256 var ohauth = require('ohauth'),
 
15257     xtend = require('xtend'),
 
15258     store = require('store');
 
15262 // This code is only compatible with IE10+ because the [XDomainRequest](http://bit.ly/LfO7xo)
 
15263 // object, IE<10's idea of [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing),
 
15264 // does not support custom headers, which this uses everywhere.
 
15265 module.exports = function(o) {
 
15269     // authenticated users will also have a request token secret, but it's
 
15270     // not used in transactions with the server
 
15271     oauth.authenticated = function() {
 
15272         return !!(token('oauth_token') && token('oauth_token_secret'));
 
15275     oauth.logout = function() {
 
15276         token('oauth_token', '');
 
15277         token('oauth_token_secret', '');
 
15278         token('oauth_request_token_secret', '');
 
15282     // TODO: detect lack of click event
 
15283     oauth.authenticate = function(callback) {
 
15284         if (oauth.authenticated()) return callback();
 
15288         // ## Getting a request token
 
15289         var params = timenonce(getAuth(o)),
 
15290             url = o.url + '/oauth/request_token',
 
15293         params.oauth_signature = ohauth.signature(
 
15294             o.oauth_secret, '',
 
15295             ohauth.baseString('POST', url, params));
 
15297         if (!o.singlepage) {
 
15298             // Create a 600x550 popup window in the center of the screen
 
15299             var w = 600, h = 550,
 
15301                     ['width', w], ['height', h],
 
15302                     ['left', screen.width / 2 - w / 2],
 
15303                     ['top', screen.height / 2 - h / 2]].map(function(x) {
 
15304                         return x.join('=');
 
15306                 popup = window.open('about:blank', 'oauth_window', settings);
 
15309             timer = setInterval(function() {
 
15310                 if (popup.closed) {
 
15312                     clearInterval(timer);
 
15313                     callback('not authenticated', null);
 
15318         // Request a request token. When this is complete, the popup
 
15319         // window is redirected to OSM's authorization page.
 
15320         ohauth.xhr('POST', url, params, null, {}, reqTokenDone);
 
15323         function reqTokenDone(err, xhr) {
 
15326                 if (timer) clearInterval(timer);
 
15327                 return callback(err);
 
15329             var resp = ohauth.stringQs(xhr.response);
 
15330             token('oauth_request_token_secret', resp.oauth_token_secret);
 
15331             var authorize_url = o.url + '/oauth/authorize?' + ohauth.qsString({
 
15332                 oauth_token: resp.oauth_token,
 
15333                 oauth_callback: location.href.replace('index.html', '')
 
15334                     .replace(/#.*/, '') + o.landing
 
15337             if (o.singlepage) {
 
15338                 location.href = authorize_url;
 
15340                 popup.location = authorize_url;
 
15344         // Called by a function in a landing page, in the popup window. The
 
15345         // window closes itself.
 
15346         window.authComplete = function(token) {
 
15347             if (timer) clearInterval(timer);
 
15348             var oauth_token = ohauth.stringQs(token.split('?')[1]);
 
15349             get_access_token(oauth_token.oauth_token);
 
15350             delete window.authComplete;
 
15353         // ## Getting an request token
 
15355         // At this point we have an `oauth_token`, brought in from a function
 
15356         // call on a landing page popup.
 
15357         function get_access_token(oauth_token) {
 
15358             var url = o.url + '/oauth/access_token',
 
15359                 params = timenonce(getAuth(o)),
 
15360                 request_token_secret = token('oauth_request_token_secret');
 
15361             params.oauth_token = oauth_token;
 
15362             params.oauth_signature = ohauth.signature(
 
15364                 request_token_secret,
 
15365                 ohauth.baseString('POST', url, params));
 
15367             // ## Getting an access token
 
15369             // The final token required for authentication. At this point
 
15370             // we have a `request token secret`
 
15371             ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
 
15375         function accessTokenDone(err, xhr) {
 
15377             if (timer) clearInterval(timer);
 
15378             if (err) return callback(err);
 
15379             var access_token = ohauth.stringQs(xhr.response);
 
15380             token('oauth_token', access_token.oauth_token);
 
15381             token('oauth_token_secret', access_token.oauth_token_secret);
 
15382             callback(null, oauth);
 
15386     oauth.bootstrapToken = function(oauth_token, callback) {
 
15387         // ## Getting an request token
 
15388         // At this point we have an `oauth_token`, brought in from a function
 
15389         // call on a landing page popup.
 
15390         function get_access_token(oauth_token) {
 
15391             var url = o.url + '/oauth/access_token',
 
15392                 params = timenonce(getAuth(o)),
 
15393                 request_token_secret = token('oauth_request_token_secret');
 
15394             params.oauth_token = oauth_token;
 
15395             params.oauth_signature = ohauth.signature(
 
15397                 request_token_secret,
 
15398                 ohauth.baseString('POST', url, params));
 
15400             // ## Getting an access token
 
15401             // The final token required for authentication. At this point
 
15402             // we have a `request token secret`
 
15403             ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
 
15407         function accessTokenDone(err, xhr) {
 
15409             if (err) return callback(err);
 
15410             var access_token = ohauth.stringQs(xhr.response);
 
15411             token('oauth_token', access_token.oauth_token);
 
15412             token('oauth_token_secret', access_token.oauth_token_secret);
 
15413             callback(null, oauth);
 
15416         get_access_token(oauth_token);
 
15421     // A single XMLHttpRequest wrapper that does authenticated calls if the
 
15422     // user has logged in.
 
15423     oauth.xhr = function(options, callback) {
 
15424         if (!oauth.authenticated()) {
 
15425             if (o.auto) return oauth.authenticate(run);
 
15426             else return callback('not authenticated', null);
 
15427         } else return run();
 
15430             var params = timenonce(getAuth(o)),
 
15431                 url = o.url + options.path,
 
15432                 oauth_token_secret = token('oauth_token_secret');
 
15434             // https://tools.ietf.org/html/rfc5849#section-3.4.1.3.1
 
15435             if ((!options.options || !options.options.header ||
 
15436                 options.options.header['Content-Type'] === 'application/x-www-form-urlencoded') &&
 
15438                 params = xtend(params, ohauth.stringQs(options.content));
 
15441             params.oauth_token = token('oauth_token');
 
15442             params.oauth_signature = ohauth.signature(
 
15444                 oauth_token_secret,
 
15445                 ohauth.baseString(options.method, url, params));
 
15447             ohauth.xhr(options.method,
 
15448                 url, params, options.content, options.options, done);
 
15451         function done(err, xhr) {
 
15452             if (err) return callback(err);
 
15453             else if (xhr.responseXML) return callback(err, xhr.responseXML);
 
15454             else return callback(err, xhr.response);
 
15458     // pre-authorize this object, if we can just get a token and token_secret
 
15460     oauth.preauth = function(c) {
 
15462         if (c.oauth_token) token('oauth_token', c.oauth_token);
 
15463         if (c.oauth_token_secret) token('oauth_token_secret', c.oauth_token_secret);
 
15467     oauth.options = function(_) {
 
15468         if (!arguments.length) return o;
 
15472         o.url = o.url || 'http://www.openstreetmap.org';
 
15473         o.landing = o.landing || 'land.html';
 
15475         o.singlepage = o.singlepage || false;
 
15477         // Optional loading and loading-done functions for nice UI feedback.
 
15478         // by default, no-ops
 
15479         o.loading = o.loading || function() {};
 
15480         o.done = o.done || function() {};
 
15482         return oauth.preauth(o);
 
15485     // 'stamp' an authentication object from `getAuth()`
 
15486     // with a [nonce](http://en.wikipedia.org/wiki/Cryptographic_nonce)
 
15488     function timenonce(o) {
 
15489         o.oauth_timestamp = ohauth.timestamp();
 
15490         o.oauth_nonce = ohauth.nonce();
 
15494     // get/set tokens. These are prefixed with the base URL so that `osm-auth`
 
15495     // can be used with multiple APIs and the keys in `localStorage`
 
15499     if (store.enabled) {
 
15500         token = function (x, y) {
 
15501             if (arguments.length === 1) return store.get(o.url + x);
 
15502             else if (arguments.length === 2) return store.set(o.url + x, y);
 
15506         token = function (x, y) {
 
15507             if (arguments.length === 1) return storage[o.url + x];
 
15508             else if (arguments.length === 2) return storage[o.url + x] = y;
 
15512     // Get an authentication object. If you just add and remove properties
 
15513     // from a single object, you'll need to use `delete` to make sure that
 
15514     // it doesn't contain undesired properties for authentication
 
15515     function getAuth(o) {
 
15517             oauth_consumer_key: o.oauth_consumer_key,
 
15518             oauth_signature_method: "HMAC-SHA1"
 
15522     // potentially pre-authorize
 
15528 },{"ohauth":2,"store":3,"xtend":4}],3:[function(require,module,exports){
 
15529 (function(global){;(function(win){
 
15531                 doc = win.document,
 
15532                 localStorageName = 'localStorage',
 
15535         store.disabled = false
 
15536         store.set = function(key, value) {}
 
15537         store.get = function(key) {}
 
15538         store.remove = function(key) {}
 
15539         store.clear = function() {}
 
15540         store.transact = function(key, defaultVal, transactionFn) {
 
15541                 var val = store.get(key)
 
15542                 if (transactionFn == null) {
 
15543                         transactionFn = defaultVal
 
15546                 if (typeof val == 'undefined') { val = defaultVal || {} }
 
15548                 store.set(key, val)
 
15550         store.getAll = function() {}
 
15551         store.forEach = function() {}
 
15553         store.serialize = function(value) {
 
15554                 return JSON.stringify(value)
 
15556         store.deserialize = function(value) {
 
15557                 if (typeof value != 'string') { return undefined }
 
15558                 try { return JSON.parse(value) }
 
15559                 catch(e) { return value || undefined }
 
15562         // Functions to encapsulate questionable FireFox 3.6.13 behavior
 
15563         // when about.config::dom.storage.enabled === false
 
15564         // See https://github.com/marcuswestin/store.js/issues#issue/13
 
15565         function isLocalStorageNameSupported() {
 
15566                 try { return (localStorageName in win && win[localStorageName]) }
 
15567                 catch(err) { return false }
 
15570         if (isLocalStorageNameSupported()) {
 
15571                 storage = win[localStorageName]
 
15572                 store.set = function(key, val) {
 
15573                         if (val === undefined) { return store.remove(key) }
 
15574                         storage.setItem(key, store.serialize(val))
 
15577                 store.get = function(key) { return store.deserialize(storage.getItem(key)) }
 
15578                 store.remove = function(key) { storage.removeItem(key) }
 
15579                 store.clear = function() { storage.clear() }
 
15580                 store.getAll = function() {
 
15582                         store.forEach(function(key, val) {
 
15587                 store.forEach = function(callback) {
 
15588                         for (var i=0; i<storage.length; i++) {
 
15589                                 var key = storage.key(i)
 
15590                                 callback(key, store.get(key))
 
15593         } else if (doc.documentElement.addBehavior) {
 
15596                 // Since #userData storage applies only to specific paths, we need to
 
15597                 // somehow link our data to a specific path.  We choose /favicon.ico
 
15598                 // as a pretty safe option, since all browsers already make a request to
 
15599                 // this URL anyway and being a 404 will not hurt us here.  We wrap an
 
15600                 // iframe pointing to the favicon in an ActiveXObject(htmlfile) object
 
15601                 // (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx)
 
15602                 // since the iframe access rules appear to allow direct access and
 
15603                 // manipulation of the document element, even for a 404 page.  This
 
15604                 // document can be used instead of the current document (which would
 
15605                 // have been limited to the current path) to perform #userData storage.
 
15607                         storageContainer = new ActiveXObject('htmlfile')
 
15608                         storageContainer.open()
 
15609                         storageContainer.write('<s' + 'cript>document.w=window</s' + 'cript><iframe src="/favicon.ico"></iframe>')
 
15610                         storageContainer.close()
 
15611                         storageOwner = storageContainer.w.frames[0].document
 
15612                         storage = storageOwner.createElement('div')
 
15614                         // somehow ActiveXObject instantiation failed (perhaps some special
 
15615                         // security settings or otherwse), fall back to per-path storage
 
15616                         storage = doc.createElement('div')
 
15617                         storageOwner = doc.body
 
15619                 function withIEStorage(storeFunction) {
 
15620                         return function() {
 
15621                                 var args = Array.prototype.slice.call(arguments, 0)
 
15622                                 args.unshift(storage)
 
15623                                 // See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx
 
15624                                 // and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx
 
15625                                 storageOwner.appendChild(storage)
 
15626                                 storage.addBehavior('#default#userData')
 
15627                                 storage.load(localStorageName)
 
15628                                 var result = storeFunction.apply(store, args)
 
15629                                 storageOwner.removeChild(storage)
 
15634                 // In IE7, keys may not contain special chars. See all of https://github.com/marcuswestin/store.js/issues/40
 
15635                 var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g")
 
15636                 function ieKeyFix(key) {
 
15637                         return key.replace(forbiddenCharsRegex, '___')
 
15639                 store.set = withIEStorage(function(storage, key, val) {
 
15640                         key = ieKeyFix(key)
 
15641                         if (val === undefined) { return store.remove(key) }
 
15642                         storage.setAttribute(key, store.serialize(val))
 
15643                         storage.save(localStorageName)
 
15646                 store.get = withIEStorage(function(storage, key) {
 
15647                         key = ieKeyFix(key)
 
15648                         return store.deserialize(storage.getAttribute(key))
 
15650                 store.remove = withIEStorage(function(storage, key) {
 
15651                         key = ieKeyFix(key)
 
15652                         storage.removeAttribute(key)
 
15653                         storage.save(localStorageName)
 
15655                 store.clear = withIEStorage(function(storage) {
 
15656                         var attributes = storage.XMLDocument.documentElement.attributes
 
15657                         storage.load(localStorageName)
 
15658                         for (var i=0, attr; attr=attributes[i]; i++) {
 
15659                                 storage.removeAttribute(attr.name)
 
15661                         storage.save(localStorageName)
 
15663                 store.getAll = function(storage) {
 
15665                         store.forEach(function(key, val) {
 
15670                 store.forEach = withIEStorage(function(storage, callback) {
 
15671                         var attributes = storage.XMLDocument.documentElement.attributes
 
15672                         for (var i=0, attr; attr=attributes[i]; ++i) {
 
15673                                 callback(attr.name, store.deserialize(storage.getAttribute(attr.name)))
 
15679                 var testKey = '__storejs__'
 
15680                 store.set(testKey, testKey)
 
15681                 if (store.get(testKey) != testKey) { store.disabled = true }
 
15682                 store.remove(testKey)
 
15684                 store.disabled = true
 
15686         store.enabled = !store.disabled
 
15688         if (typeof module != 'undefined' && module.exports) { module.exports = store }
 
15689         else if (typeof define === 'function' && define.amd) { define(store) }
 
15690         else { win.store = store }
 
15692 })(this.window || global);
 
15695 },{}],5:[function(require,module,exports){
 
15696 module.exports = hasKeys
 
15698 function hasKeys(source) {
 
15699     return source !== null &&
 
15700         (typeof source === "object" ||
 
15701         typeof source === "function")
 
15704 },{}],4:[function(require,module,exports){
 
15705 var Keys = require("object-keys")
 
15706 var hasKeys = require("./has-keys")
 
15708 module.exports = extend
 
15710 function extend() {
 
15713     for (var i = 0; i < arguments.length; i++) {
 
15714         var source = arguments[i]
 
15716         if (!hasKeys(source)) {
 
15720         var keys = Keys(source)
 
15722         for (var j = 0; j < keys.length; j++) {
 
15724             target[name] = source[name]
 
15731 },{"./has-keys":5,"object-keys":6}],7:[function(require,module,exports){
 
15732 (function(global){/**
 
15733  * jsHashes - A fast and independent hashing library pure JavaScript implemented (ES3 compliant) for both server and client side
 
15736  * @author Tomas Aparicio <tomas@rijndael-project.com>
 
15737  * @license New BSD (see LICENSE file)
 
15740  * Algorithms specification:
 
15742  * MD5 <http://www.ietf.org/rfc/rfc1321.txt>
 
15743  * RIPEMD-160 <http://homes.esat.kuleuven.be/~bosselae/ripemd160.html>
 
15744  * SHA1   <http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf>
 
15745  * SHA256 <http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf>
 
15746  * SHA512 <http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf>
 
15747  * HMAC <http://www.ietf.org/rfc/rfc2104.txt>
 
15753   // private helper methods
 
15754   function utf8Encode(str) {
 
15755     var  x, y, output = '', i = -1, l;
 
15757     if (str && str.length) {
 
15759       while ((i+=1) < l) {
 
15760         /* Decode utf-16 surrogate pairs */
 
15761         x = str.charCodeAt(i);
 
15762         y = i + 1 < l ? str.charCodeAt(i + 1) : 0;
 
15763         if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) {
 
15764             x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
 
15767         /* Encode output as utf-8 */
 
15769             output += String.fromCharCode(x);
 
15770         } else if (x <= 0x7FF) {
 
15771             output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F),
 
15772                         0x80 | ( x & 0x3F));
 
15773         } else if (x <= 0xFFFF) {
 
15774             output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
 
15775                         0x80 | ((x >>> 6 ) & 0x3F),
 
15776                         0x80 | ( x & 0x3F));
 
15777         } else if (x <= 0x1FFFFF) {
 
15778             output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
 
15779                         0x80 | ((x >>> 12) & 0x3F),
 
15780                         0x80 | ((x >>> 6 ) & 0x3F),
 
15781                         0x80 | ( x & 0x3F));
 
15788   function utf8Decode(str) {
 
15789     var i, ac, c1, c2, c3, arr = [], l;
 
15790     i = ac = c1 = c2 = c3 = 0;
 
15792     if (str && str.length) {
 
15797           c1 = str.charCodeAt(i);
 
15800               arr[ac] = String.fromCharCode(c1);
 
15802           } else if (c1 > 191 && c1 < 224) {
 
15803               c2 = str.charCodeAt(i + 1);
 
15804               arr[ac] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
 
15807               c2 = str.charCodeAt(i + 1);
 
15808               c3 = str.charCodeAt(i + 2);
 
15809               arr[ac] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
 
15814     return arr.join('');
 
15818    * Add integers, wrapping at 2^32. This uses 16-bit operations internally
 
15819    * to work around bugs in some JS interpreters.
 
15821   function safe_add(x, y) {
 
15822     var lsw = (x & 0xFFFF) + (y & 0xFFFF),
 
15823         msw = (x >> 16) + (y >> 16) + (lsw >> 16);
 
15824     return (msw << 16) | (lsw & 0xFFFF);
 
15828    * Bitwise rotate a 32-bit number to the left.
 
15830   function bit_rol(num, cnt) {
 
15831     return (num << cnt) | (num >>> (32 - cnt));
 
15835    * Convert a raw string to a hex string
 
15837   function rstr2hex(input, hexcase) {
 
15838     var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef',
 
15839         output = '', x, i = 0, l = input.length;
 
15840     for (; i < l; i+=1) {
 
15841       x = input.charCodeAt(i);
 
15842       output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt(x & 0x0F);
 
15848    * Encode a string as utf-16
 
15850   function str2rstr_utf16le(input) {
 
15851     var i, l = input.length, output = '';
 
15852     for (i = 0; i < l; i+=1) {
 
15853       output += String.fromCharCode( input.charCodeAt(i) & 0xFF, (input.charCodeAt(i) >>> 8) & 0xFF);
 
15858   function str2rstr_utf16be(input) {
 
15859     var i, l = input.length, output = '';
 
15860     for (i = 0; i < l; i+=1) {
 
15861       output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, input.charCodeAt(i) & 0xFF);
 
15867    * Convert an array of big-endian words to a string
 
15869   function binb2rstr(input) {
 
15870     var i, l = input.length * 32, output = '';
 
15871     for (i = 0; i < l; i += 8) {
 
15872         output += String.fromCharCode((input[i>>5] >>> (24 - i % 32)) & 0xFF);
 
15878    * Convert an array of little-endian words to a string
 
15880   function binl2rstr(input) {
 
15881     var i, l = input.length * 32, output = '';
 
15882     for (i = 0;i < l; i += 8) {
 
15883       output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
 
15889    * Convert a raw string to an array of little-endian words
 
15890    * Characters >255 have their high-byte silently ignored.
 
15892   function rstr2binl(input) {
 
15893     var i, l = input.length * 8, output = Array(input.length >> 2), lo = output.length;
 
15894     for (i = 0; i < lo; i+=1) {
 
15897     for (i = 0; i < l; i += 8) {
 
15898       output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (i%32);
 
15904    * Convert a raw string to an array of big-endian words
 
15905    * Characters >255 have their high-byte silently ignored.
 
15907    function rstr2binb(input) {
 
15908       var i, l = input.length * 8, output = Array(input.length >> 2), lo = output.length;
 
15909       for (i = 0; i < lo; i+=1) {
 
15912       for (i = 0; i < l; i += 8) {
 
15913             output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
 
15919    * Convert a raw string to an arbitrary string encoding
 
15921   function rstr2any(input, encoding) {
 
15922     var divisor = encoding.length,
 
15923         remainders = Array(),
 
15924         i, q, x, ld, quotient, dividend, output, full_length;
 
15926     /* Convert to an array of 16-bit big-endian values, forming the dividend */
 
15927     dividend = Array(Math.ceil(input.length / 2));
 
15928     ld = dividend.length;
 
15929     for (i = 0; i < ld; i+=1) {
 
15930       dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
 
15934      * Repeatedly perform a long division. The binary array forms the dividend,
 
15935      * the length of the encoding is the divisor. Once computed, the quotient
 
15936      * forms the dividend for the next step. We stop when the dividend is zerHashes.
 
15937      * All remainders are stored for later use.
 
15939     while(dividend.length > 0) {
 
15940       quotient = Array();
 
15942       for (i = 0; i < dividend.length; i+=1) {
 
15943         x = (x << 16) + dividend[i];
 
15944         q = Math.floor(x / divisor);
 
15946         if (quotient.length > 0 || q > 0) {
 
15947           quotient[quotient.length] = q;
 
15950       remainders[remainders.length] = x;
 
15951       dividend = quotient;
 
15954     /* Convert the remainders to the output string */
 
15956     for (i = remainders.length - 1; i >= 0; i--) {
 
15957       output += encoding.charAt(remainders[i]);
 
15960     /* Append leading zero equivalents */
 
15961     full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2)));
 
15962     for (i = output.length; i < full_length; i+=1) {
 
15963       output = encoding[0] + output;
 
15969    * Convert a raw string to a base-64 string
 
15971   function rstr2b64(input, b64pad) {
 
15972     var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
 
15974         len = input.length, i, j, triplet;
 
15975     b64pad= b64pad || '=';
 
15976     for (i = 0; i < len; i += 3) {
 
15977       triplet = (input.charCodeAt(i) << 16)
 
15978             | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
 
15979             | (i + 2 < len ? input.charCodeAt(i+2)      : 0);
 
15980       for (j = 0; j < 4; j+=1) {
 
15981         if (i * 8 + j * 6 > input.length * 8) {
 
15984           output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
 
15993    * @property {String} version
 
16002   Base64 : function () {
 
16003     // private properties
 
16004     var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
 
16005         pad = '=', // default pad according with the RFC standard
 
16006         url = false, // URL encoding support @todo
 
16007         utf8 = true; // by default enable UTF-8 support encoding
 
16009     // public method for encoding
 
16010     this.encode = function (input) {
 
16013           len = input.length;
 
16016       input = (utf8) ? utf8Encode(input) : input;
 
16018       for (i = 0; i < len; i += 3) {
 
16019         triplet = (input.charCodeAt(i) << 16)
 
16020               | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0)
 
16021               | (i + 2 < len ? input.charCodeAt(i+2) : 0);
 
16022         for (j = 0; j < 4; j+=1) {
 
16023           if (i * 8 + j * 6 > len * 8) {
 
16026               output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F);
 
16033     // public method for decoding
 
16034     this.decode = function (input) {
 
16035       // var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
 
16036       var i, o1, o2, o3, h1, h2, h3, h4, bits, ac,
 
16039       if (!input) { return input; }
 
16042       input = input.replace(new RegExp('\\'+pad,'gi'),''); // use '='
 
16045       do { // unpack four hexets into three octets using index points in b64
 
16046         h1 = tab.indexOf(input.charAt(i+=1));
 
16047         h2 = tab.indexOf(input.charAt(i+=1));
 
16048         h3 = tab.indexOf(input.charAt(i+=1));
 
16049         h4 = tab.indexOf(input.charAt(i+=1));
 
16051         bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
 
16053         o1 = bits >> 16 & 0xff;
 
16054         o2 = bits >> 8 & 0xff;
 
16059           arr[ac] = String.fromCharCode(o1);
 
16060         } else if (h4 === 64) {
 
16061           arr[ac] = String.fromCharCode(o1, o2);
 
16063           arr[ac] = String.fromCharCode(o1, o2, o3);
 
16065       } while (i < input.length);
 
16067       dec = arr.join('');
 
16068       dec = (utf8) ? utf8Decode(dec) : dec;
 
16073     // set custom pad string
 
16074     this.setPad = function (str) {
 
16078     // set custom tab string characters
 
16079     this.setTab = function (str) {
 
16083     this.setUTF8 = function (bool) {
 
16084         if (typeof bool === 'boolean') {
 
16092    * CRC-32 calculation
 
16096    * @param {String} str Input String
 
16099   CRC32 : function (str) {
 
16100     var crc = 0, x = 0, y = 0, table, i, iTop;
 
16101     str = utf8Encode(str);
 
16104         '00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 ',
 
16105         '79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 ',
 
16106         '84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F ',
 
16107         '63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD ',
 
16108         'A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC ',
 
16109         '51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 ',
 
16110         'B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 ',
 
16111         '06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 ',
 
16112         'E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 ',
 
16113         '12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 ',
 
16114         'D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 ',
 
16115         '33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 ',
 
16116         'CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 ',
 
16117         '9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E ',
 
16118         '7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D ',
 
16119         '806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 ',
 
16120         '60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA ',
 
16121         'AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 ',
 
16122         '5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 ',
 
16123         'B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 ',
 
16124         '05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 ',
 
16125         'F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA ',
 
16126         '11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 ',
 
16127         'D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F ',
 
16128         '30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E ',
 
16129         'C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D'
 
16133     for (i = 0, iTop = str.length; i < iTop; i+=1 ) {
 
16134         y = ( crc ^ str.charCodeAt( i ) ) & 0xFF;
 
16135         x = '0x' + table.substr( y * 9, 8 );
 
16136         crc = ( crc >>> 8 ) ^ x;
 
16138     // always return a positive number (that's what >>> 0 does)
 
16139     return (crc ^ (-1)) >>> 0;
 
16145    * @param {Object} [config]
 
16147    * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
 
16148    * Digest Algorithm, as defined in RFC 1321.
 
16149    * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
 
16150    * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 
16151    * See <http://pajhome.org.uk/crypt/md5> for more infHashes.
 
16153   MD5 : function (options) {
 
16155      * Private config properties. You may need to tweak these to be compatible with
 
16156      * the server-side, but the defaults work in most cases.
 
16157      * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
 
16159     var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
 
16160         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
 
16161         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
 
16163     // privileged (public) methods
 
16164     this.hex = function (s) {
 
16165       return rstr2hex(rstr(s, utf8), hexcase);
 
16167     this.b64 = function (s) {
 
16168       return rstr2b64(rstr(s), b64pad);
 
16170     this.any = function(s, e) {
 
16171       return rstr2any(rstr(s, utf8), e);
 
16173     this.hex_hmac = function (k, d) {
 
16174       return rstr2hex(rstr_hmac(k, d), hexcase);
 
16176     this.b64_hmac = function (k, d) {
 
16177       return rstr2b64(rstr_hmac(k,d), b64pad);
 
16179     this.any_hmac = function (k, d, e) {
 
16180       return rstr2any(rstr_hmac(k, d), e);
 
16183      * Perform a simple self-test to see if the VM is working
 
16184      * @return {String} Hexadecimal hash sample
 
16186     this.vm_test = function () {
 
16187       return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
 
16190      * Enable/disable uppercase hexadecimal returned string
 
16192      * @return {Object} this
 
16194     this.setUpperCase = function (a) {
 
16195       if (typeof a === 'boolean' ) {
 
16201      * Defines a base64 pad string
 
16202      * @param {String} Pad
 
16203      * @return {Object} this
 
16205     this.setPad = function (a) {
 
16206       b64pad = a || b64pad;
 
16210      * Defines a base64 pad string
 
16212      * @return {Object} [this]
 
16214     this.setUTF8 = function (a) {
 
16215       if (typeof a === 'boolean') {
 
16224      * Calculate the MD5 of a raw string
 
16227       s = (utf8) ? utf8Encode(s): s;
 
16228       return binl2rstr(binl(rstr2binl(s), s.length * 8));
 
16232      * Calculate the HMAC-MD5, of a key and some data (raw strings)
 
16234     function rstr_hmac(key, data) {
 
16235       var bkey, ipad, opad, hash, i;
 
16237       key = (utf8) ? utf8Encode(key) : key;
 
16238       data = (utf8) ? utf8Encode(data) : data;
 
16239       bkey = rstr2binl(key);
 
16240       if (bkey.length > 16) {
 
16241         bkey = binl(bkey, key.length * 8);
 
16244       ipad = Array(16), opad = Array(16);
 
16245       for (i = 0; i < 16; i+=1) {
 
16246           ipad[i] = bkey[i] ^ 0x36363636;
 
16247           opad[i] = bkey[i] ^ 0x5C5C5C5C;
 
16249       hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
 
16250       return binl2rstr(binl(opad.concat(hash), 512 + 128));
 
16254      * Calculate the MD5 of an array of little-endian words, and a bit length.
 
16256     function binl(x, len) {
 
16257       var i, olda, oldb, oldc, oldd,
 
16263       /* append padding */
 
16264       x[len >> 5] |= 0x80 << ((len) % 32);
 
16265       x[(((len + 64) >>> 9) << 4) + 14] = len;
 
16267       for (i = 0; i < x.length; i += 16) {
 
16273         a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);
 
16274         d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);
 
16275         c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);
 
16276         b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);
 
16277         a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);
 
16278         d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);
 
16279         c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);
 
16280         b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);
 
16281         a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);
 
16282         d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);
 
16283         c = md5_ff(c, d, a, b, x[i+10], 17, -42063);
 
16284         b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);
 
16285         a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);
 
16286         d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);
 
16287         c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);
 
16288         b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);
 
16290         a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);
 
16291         d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);
 
16292         c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);
 
16293         b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);
 
16294         a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);
 
16295         d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);
 
16296         c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);
 
16297         b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);
 
16298         a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);
 
16299         d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);
 
16300         c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);
 
16301         b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);
 
16302         a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);
 
16303         d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);
 
16304         c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);
 
16305         b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);
 
16307         a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);
 
16308         d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);
 
16309         c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);
 
16310         b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);
 
16311         a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);
 
16312         d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);
 
16313         c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);
 
16314         b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);
 
16315         a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);
 
16316         d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);
 
16317         c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);
 
16318         b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);
 
16319         a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);
 
16320         d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);
 
16321         c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);
 
16322         b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);
 
16324         a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);
 
16325         d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);
 
16326         c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);
 
16327         b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);
 
16328         a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);
 
16329         d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);
 
16330         c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);
 
16331         b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);
 
16332         a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);
 
16333         d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);
 
16334         c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);
 
16335         b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);
 
16336         a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);
 
16337         d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);
 
16338         c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);
 
16339         b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);
 
16341         a = safe_add(a, olda);
 
16342         b = safe_add(b, oldb);
 
16343         c = safe_add(c, oldc);
 
16344         d = safe_add(d, oldd);
 
16346       return Array(a, b, c, d);
 
16350      * These functions implement the four basic operations the algorithm uses.
 
16352     function md5_cmn(q, a, b, x, s, t) {
 
16353       return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);
 
16355     function md5_ff(a, b, c, d, x, s, t) {
 
16356       return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
 
16358     function md5_gg(a, b, c, d, x, s, t) {
 
16359       return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
 
16361     function md5_hh(a, b, c, d, x, s, t) {
 
16362       return md5_cmn(b ^ c ^ d, a, b, x, s, t);
 
16364     function md5_ii(a, b, c, d, x, s, t) {
 
16365       return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
 
16370    * @class Hashes.SHA1
 
16371    * @param {Object} [config]
 
16374    * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS 180-1
 
16375    * Version 2.2 Copyright Paul Johnston 2000 - 2009.
 
16376    * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 
16377    * See http://pajhome.org.uk/crypt/md5 for details.
 
16379   SHA1 : function (options) {
 
16381      * Private config properties. You may need to tweak these to be compatible with
 
16382      * the server-side, but the defaults work in most cases.
 
16383      * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
 
16385     var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
 
16386         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
 
16387         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
 
16390     this.hex = function (s) {
 
16391         return rstr2hex(rstr(s, utf8), hexcase);
 
16393     this.b64 = function (s) {
 
16394         return rstr2b64(rstr(s, utf8), b64pad);
 
16396     this.any = function (s, e) {
 
16397         return rstr2any(rstr(s, utf8), e);
 
16399     this.hex_hmac = function (k, d) {
 
16400         return rstr2hex(rstr_hmac(k, d));
 
16402     this.b64_hmac = function (k, d) {
 
16403         return rstr2b64(rstr_hmac(k, d), b64pad);
 
16405     this.any_hmac = function (k, d, e) {
 
16406         return rstr2any(rstr_hmac(k, d), e);
 
16409      * Perform a simple self-test to see if the VM is working
 
16410      * @return {String} Hexadecimal hash sample
 
16413     this.vm_test = function () {
 
16414       return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
 
16417      * @description Enable/disable uppercase hexadecimal returned string
 
16419      * @return {Object} this
 
16422     this.setUpperCase = function (a) {
 
16423         if (typeof a === 'boolean') {
 
16429      * @description Defines a base64 pad string
 
16430      * @param {string} Pad
 
16431      * @return {Object} this
 
16434     this.setPad = function (a) {
 
16435       b64pad = a || b64pad;
 
16439      * @description Defines a base64 pad string
 
16441      * @return {Object} this
 
16444     this.setUTF8 = function (a) {
 
16445         if (typeof a === 'boolean') {
 
16454          * Calculate the SHA-512 of a raw string
 
16457       s = (utf8) ? utf8Encode(s) : s;
 
16458       return binb2rstr(binb(rstr2binb(s), s.length * 8));
 
16462      * Calculate the HMAC-SHA1 of a key and some data (raw strings)
 
16464     function rstr_hmac(key, data) {
 
16465         var bkey, ipad, opad, i, hash;
 
16466         key = (utf8) ? utf8Encode(key) : key;
 
16467         data = (utf8) ? utf8Encode(data) : data;
 
16468         bkey = rstr2binb(key);
 
16470         if (bkey.length > 16) {
 
16471         bkey = binb(bkey, key.length * 8);
 
16473         ipad = Array(16), opad = Array(16);
 
16474         for (i = 0; i < 16; i+=1) {
 
16475                 ipad[i] = bkey[i] ^ 0x36363636;
 
16476                 opad[i] = bkey[i] ^ 0x5C5C5C5C;
 
16478         hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
 
16479         return binb2rstr(binb(opad.concat(hash), 512 + 160));
 
16483      * Calculate the SHA-1 of an array of big-endian words, and a bit length
 
16485     function binb(x, len) {
 
16486       var i, j, t, olda, oldb, oldc, oldd, olde,
 
16494       /* append padding */
 
16495       x[len >> 5] |= 0x80 << (24 - len % 32);
 
16496       x[((len + 64 >> 9) << 4) + 15] = len;
 
16498       for (i = 0; i < x.length; i += 16) {
 
16505         for (j = 0; j < 80; j+=1)       {
 
16509             w[j] = bit_rol(w[j-3] ^ w[j-8] ^ w[j-14] ^ w[j-16], 1);
 
16511           t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)),
 
16512                                            safe_add(safe_add(e, w[j]), sha1_kt(j)));
 
16515           c = bit_rol(b, 30);
 
16520         a = safe_add(a, olda);
 
16521         b = safe_add(b, oldb);
 
16522         c = safe_add(c, oldc);
 
16523         d = safe_add(d, oldd);
 
16524         e = safe_add(e, olde);
 
16526       return Array(a, b, c, d, e);
 
16530      * Perform the appropriate triplet combination function for the current
 
16533     function sha1_ft(t, b, c, d) {
 
16534       if (t < 20) { return (b & c) | ((~b) & d); }
 
16535       if (t < 40) { return b ^ c ^ d; }
 
16536       if (t < 60) { return (b & c) | (b & d) | (c & d); }
 
16541      * Determine the appropriate additive constant for the current iteration
 
16543     function sha1_kt(t) {
 
16544       return (t < 20) ?  1518500249 : (t < 40) ?  1859775393 :
 
16545                  (t < 60) ? -1894007588 : -899497514;
 
16549    * @class Hashes.SHA256
 
16552    * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined in FIPS 180-2
 
16553    * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009.
 
16554    * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 
16555    * See http://pajhome.org.uk/crypt/md5 for details.
 
16556    * Also http://anmar.eu.org/projects/jssha2/
 
16558   SHA256 : function (options) {
 
16560      * Private properties configuration variables. You may need to tweak these to be compatible with
 
16561      * the server-side, but the defaults work in most cases.
 
16562      * @see this.setUpperCase() method
 
16563      * @see this.setPad() method
 
16565     var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase  */
 
16566               b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', /* base-64 pad character. Default '=' for strict RFC compliance   */
 
16567               utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, /* enable/disable utf8 encoding */
 
16570     /* privileged (public) methods */
 
16571     this.hex = function (s) {
 
16572       return rstr2hex(rstr(s, utf8));
 
16574     this.b64 = function (s) {
 
16575       return rstr2b64(rstr(s, utf8), b64pad);
 
16577     this.any = function (s, e) {
 
16578       return rstr2any(rstr(s, utf8), e);
 
16580     this.hex_hmac = function (k, d) {
 
16581       return rstr2hex(rstr_hmac(k, d));
 
16583     this.b64_hmac = function (k, d) {
 
16584       return rstr2b64(rstr_hmac(k, d), b64pad);
 
16586     this.any_hmac = function (k, d, e) {
 
16587       return rstr2any(rstr_hmac(k, d), e);
 
16590      * Perform a simple self-test to see if the VM is working
 
16591      * @return {String} Hexadecimal hash sample
 
16594     this.vm_test = function () {
 
16595       return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
 
16598      * Enable/disable uppercase hexadecimal returned string
 
16600      * @return {Object} this
 
16603     this.setUpperCase = function (a) {
 
16604       if (typeof a === 'boolean') {
 
16610      * @description Defines a base64 pad string
 
16611      * @param {string} Pad
 
16612      * @return {Object} this
 
16615     this.setPad = function (a) {
 
16616       b64pad = a || b64pad;
 
16620      * Defines a base64 pad string
 
16622      * @return {Object} this
 
16625     this.setUTF8 = function (a) {
 
16626       if (typeof a === 'boolean') {
 
16635      * Calculate the SHA-512 of a raw string
 
16637     function rstr(s, utf8) {
 
16638       s = (utf8) ? utf8Encode(s) : s;
 
16639       return binb2rstr(binb(rstr2binb(s), s.length * 8));
 
16643      * Calculate the HMAC-sha256 of a key and some data (raw strings)
 
16645     function rstr_hmac(key, data) {
 
16646       key = (utf8) ? utf8Encode(key) : key;
 
16647       data = (utf8) ? utf8Encode(data) : data;
 
16649           bkey = rstr2binb(key),
 
16653       if (bkey.length > 16) { bkey = binb(bkey, key.length * 8); }
 
16655       for (; i < 16; i+=1) {
 
16656         ipad[i] = bkey[i] ^ 0x36363636;
 
16657         opad[i] = bkey[i] ^ 0x5C5C5C5C;
 
16660       hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
 
16661       return binb2rstr(binb(opad.concat(hash), 512 + 256));
 
16665      * Main sha256 function, with its support functions
 
16667     function sha256_S (X, n) {return ( X >>> n ) | (X << (32 - n));}
 
16668     function sha256_R (X, n) {return ( X >>> n );}
 
16669     function sha256_Ch(x, y, z) {return ((x & y) ^ ((~x) & z));}
 
16670     function sha256_Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));}
 
16671     function sha256_Sigma0256(x) {return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22));}
 
16672     function sha256_Sigma1256(x) {return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25));}
 
16673     function sha256_Gamma0256(x) {return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3));}
 
16674     function sha256_Gamma1256(x) {return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10));}
 
16675     function sha256_Sigma0512(x) {return (sha256_S(x, 28) ^ sha256_S(x, 34) ^ sha256_S(x, 39));}
 
16676     function sha256_Sigma1512(x) {return (sha256_S(x, 14) ^ sha256_S(x, 18) ^ sha256_S(x, 41));}
 
16677     function sha256_Gamma0512(x) {return (sha256_S(x, 1)  ^ sha256_S(x, 8) ^ sha256_R(x, 7));}
 
16678     function sha256_Gamma1512(x) {return (sha256_S(x, 19) ^ sha256_S(x, 61) ^ sha256_R(x, 6));}
 
16681       1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993,
 
16682       -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987,
 
16683       1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522,
 
16684       264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986,
 
16685       -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585,
 
16686       113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291,
 
16687       1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885,
 
16688       -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344,
 
16689       430227734, 506948616, 659060556, 883997877, 958139571, 1322822218,
 
16690       1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872,
 
16691       -1866530822, -1538233109, -1090935817, -965641998
 
16694     function binb(m, l) {
 
16695       var HASH = [1779033703, -1150833019, 1013904242, -1521486534,
 
16696                  1359893119, -1694144372, 528734635, 1541459225];
 
16697       var W = new Array(64);
 
16698       var a, b, c, d, e, f, g, h;
 
16701       /* append padding */
 
16702       m[l >> 5] |= 0x80 << (24 - l % 32);
 
16703       m[((l + 64 >> 9) << 4) + 15] = l;
 
16705       for (i = 0; i < m.length; i += 16)
 
16716       for (j = 0; j < 64; j+=1)
 
16721           W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]),
 
16722                           sha256_Gamma0256(W[j - 15])), W[j - 16]);
 
16725         T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)),
 
16726                                   sha256_K[j]), W[j]);
 
16727         T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c));
 
16731         e = safe_add(d, T1);
 
16735         a = safe_add(T1, T2);
 
16738       HASH[0] = safe_add(a, HASH[0]);
 
16739       HASH[1] = safe_add(b, HASH[1]);
 
16740       HASH[2] = safe_add(c, HASH[2]);
 
16741       HASH[3] = safe_add(d, HASH[3]);
 
16742       HASH[4] = safe_add(e, HASH[4]);
 
16743       HASH[5] = safe_add(f, HASH[5]);
 
16744       HASH[6] = safe_add(g, HASH[6]);
 
16745       HASH[7] = safe_add(h, HASH[7]);
 
16753    * @class Hashes.SHA512
 
16756    * A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined in FIPS 180-2
 
16757    * Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009.
 
16758    * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 
16759    * See http://pajhome.org.uk/crypt/md5 for details.
 
16761   SHA512 : function (options) {
 
16763      * Private properties configuration variables. You may need to tweak these to be compatible with
 
16764      * the server-side, but the defaults work in most cases.
 
16765      * @see this.setUpperCase() method
 
16766      * @see this.setPad() method
 
16768     var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false , /* hexadecimal output case format. false - lowercase; true - uppercase  */
 
16769         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',  /* base-64 pad character. Default '=' for strict RFC compliance   */
 
16770         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, /* enable/disable utf8 encoding */
 
16773     /* privileged (public) methods */
 
16774     this.hex = function (s) {
 
16775       return rstr2hex(rstr(s));
 
16777     this.b64 = function (s) {
 
16778       return rstr2b64(rstr(s), b64pad);
 
16780     this.any = function (s, e) {
 
16781       return rstr2any(rstr(s), e);
 
16783     this.hex_hmac = function (k, d) {
 
16784       return rstr2hex(rstr_hmac(k, d));
 
16786     this.b64_hmac = function (k, d) {
 
16787       return rstr2b64(rstr_hmac(k, d), b64pad);
 
16789     this.any_hmac = function (k, d, e) {
 
16790       return rstr2any(rstr_hmac(k, d), e);
 
16793      * Perform a simple self-test to see if the VM is working
 
16794      * @return {String} Hexadecimal hash sample
 
16797     this.vm_test = function () {
 
16798       return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
 
16801      * @description Enable/disable uppercase hexadecimal returned string
 
16803      * @return {Object} this
 
16806     this.setUpperCase = function (a) {
 
16807       if (typeof a === 'boolean') {
 
16813      * @description Defines a base64 pad string
 
16814      * @param {string} Pad
 
16815      * @return {Object} this
 
16818     this.setPad = function (a) {
 
16819       b64pad = a || b64pad;
 
16823      * @description Defines a base64 pad string
 
16825      * @return {Object} this
 
16828     this.setUTF8 = function (a) {
 
16829       if (typeof a === 'boolean') {
 
16835     /* private methods */
 
16838      * Calculate the SHA-512 of a raw string
 
16841       s = (utf8) ? utf8Encode(s) : s;
 
16842       return binb2rstr(binb(rstr2binb(s), s.length * 8));
 
16845      * Calculate the HMAC-SHA-512 of a key and some data (raw strings)
 
16847     function rstr_hmac(key, data) {
 
16848       key = (utf8) ? utf8Encode(key) : key;
 
16849       data = (utf8) ? utf8Encode(data) : data;
 
16852           bkey = rstr2binb(key),
 
16853           ipad = Array(32), opad = Array(32);
 
16855       if (bkey.length > 32) { bkey = binb(bkey, key.length * 8); }
 
16857       for (; i < 32; i+=1) {
 
16858         ipad[i] = bkey[i] ^ 0x36363636;
 
16859         opad[i] = bkey[i] ^ 0x5C5C5C5C;
 
16862       hash = binb(ipad.concat(rstr2binb(data)), 1024 + data.length * 8);
 
16863       return binb2rstr(binb(opad.concat(hash), 1024 + 512));
 
16867      * Calculate the SHA-512 of an array of big-endian dwords, and a bit length
 
16869     function binb(x, len) {
 
16872           hash = new Array(16),
 
16873           //Initial hash values
 
16875             new int64(0x6a09e667, -205731576),
 
16876             new int64(-1150833019, -2067093701),
 
16877             new int64(0x3c6ef372, -23791573),
 
16878             new int64(-1521486534, 0x5f1d36f1),
 
16879             new int64(0x510e527f, -1377402159),
 
16880             new int64(-1694144372, 0x2b3e6c1f),
 
16881             new int64(0x1f83d9ab, -79577749),
 
16882             new int64(0x5be0cd19, 0x137e2179)
 
16884           T1 = new int64(0, 0),
 
16885           T2 = new int64(0, 0),
 
16886           a = new int64(0,0),
 
16887           b = new int64(0,0),
 
16888           c = new int64(0,0),
 
16889           d = new int64(0,0),
 
16890           e = new int64(0,0),
 
16891           f = new int64(0,0),
 
16892           g = new int64(0,0),
 
16893           h = new int64(0,0),
 
16894           //Temporary variables not specified by the document
 
16895           s0 = new int64(0, 0),
 
16896           s1 = new int64(0, 0),
 
16897           Ch = new int64(0, 0),
 
16898           Maj = new int64(0, 0),
 
16899           r1 = new int64(0, 0),
 
16900           r2 = new int64(0, 0),
 
16901           r3 = new int64(0, 0);
 
16903       if (sha512_k === undefined) {
 
16906             new int64(0x428a2f98, -685199838), new int64(0x71374491, 0x23ef65cd),
 
16907             new int64(-1245643825, -330482897), new int64(-373957723, -2121671748),
 
16908             new int64(0x3956c25b, -213338824), new int64(0x59f111f1, -1241133031),
 
16909             new int64(-1841331548, -1357295717), new int64(-1424204075, -630357736),
 
16910             new int64(-670586216, -1560083902), new int64(0x12835b01, 0x45706fbe),
 
16911             new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, -704662302),
 
16912             new int64(0x72be5d74, -226784913), new int64(-2132889090, 0x3b1696b1),
 
16913             new int64(-1680079193, 0x25c71235), new int64(-1046744716, -815192428),
 
16914             new int64(-459576895, -1628353838), new int64(-272742522, 0x384f25e3),
 
16915             new int64(0xfc19dc6, -1953704523), new int64(0x240ca1cc, 0x77ac9c65),
 
16916             new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483),
 
16917             new int64(0x5cb0a9dc, -1119749164), new int64(0x76f988da, -2096016459),
 
16918             new int64(-1740746414, -295247957), new int64(-1473132947, 0x2db43210),
 
16919             new int64(-1341970488, -1728372417), new int64(-1084653625, -1091629340),
 
16920             new int64(-958395405, 0x3da88fc2), new int64(-710438585, -1828018395),
 
16921             new int64(0x6ca6351, -536640913), new int64(0x14292967, 0xa0e6e70),
 
16922             new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926),
 
16923             new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, -1651133473),
 
16924             new int64(0x650a7354, -1951439906), new int64(0x766a0abb, 0x3c77b2a8),
 
16925             new int64(-2117940946, 0x47edaee6), new int64(-1838011259, 0x1482353b),
 
16926             new int64(-1564481375, 0x4cf10364), new int64(-1474664885, -1136513023),
 
16927             new int64(-1035236496, -789014639), new int64(-949202525, 0x654be30),
 
16928             new int64(-778901479, -688958952), new int64(-694614492, 0x5565a910),
 
16929             new int64(-200395387, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8),
 
16930             new int64(0x19a4c116, -1194143544), new int64(0x1e376c08, 0x5141ab53),
 
16931             new int64(0x2748774c, -544281703), new int64(0x34b0bcb5, -509917016),
 
16932             new int64(0x391c0cb3, -976659869), new int64(0x4ed8aa4a, -482243893),
 
16933             new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, -692930397),
 
16934             new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60),
 
16935             new int64(-2067236844, -1578062990), new int64(-1933114872, 0x1a6439ec),
 
16936             new int64(-1866530822, 0x23631e28), new int64(-1538233109, -561857047),
 
16937             new int64(-1090935817, -1295615723), new int64(-965641998, -479046869),
 
16938             new int64(-903397682, -366583396), new int64(-779700025, 0x21c0c207),
 
16939             new int64(-354779690, -840897762), new int64(-176337025, -294727304),
 
16940             new int64(0x6f067aa, 0x72176fba), new int64(0xa637dc5, -1563912026),
 
16941             new int64(0x113f9804, -1090974290), new int64(0x1b710b35, 0x131c471b),
 
16942             new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493),
 
16943             new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, -1676669620),
 
16944             new int64(0x4cc5d4be, -885112138), new int64(0x597f299c, -60457430),
 
16945             new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)
 
16949       for (i=0; i<80; i+=1) {
 
16950         W[i] = new int64(0, 0);
 
16953       // append padding to the source string. The format is described in the FIPS.
 
16954       x[len >> 5] |= 0x80 << (24 - (len & 0x1f));
 
16955       x[((len + 128 >> 10)<< 5) + 31] = len;
 
16957       for (i = 0; i<l; i+=32) { //32 dwords is the block size
 
16958         int64copy(a, H[0]);
 
16959         int64copy(b, H[1]);
 
16960         int64copy(c, H[2]);
 
16961         int64copy(d, H[3]);
 
16962         int64copy(e, H[4]);
 
16963         int64copy(f, H[5]);
 
16964         int64copy(g, H[6]);
 
16965         int64copy(h, H[7]);
 
16967         for (j=0; j<16; j+=1) {
 
16968           W[j].h = x[i + 2*j];
 
16969           W[j].l = x[i + 2*j + 1];
 
16972         for (j=16; j<80; j+=1) {
 
16974           int64rrot(r1, W[j-2], 19);
 
16975           int64revrrot(r2, W[j-2], 29);
 
16976           int64shr(r3, W[j-2], 6);
 
16977           s1.l = r1.l ^ r2.l ^ r3.l;
 
16978           s1.h = r1.h ^ r2.h ^ r3.h;
 
16980           int64rrot(r1, W[j-15], 1);
 
16981           int64rrot(r2, W[j-15], 8);
 
16982           int64shr(r3, W[j-15], 7);
 
16983           s0.l = r1.l ^ r2.l ^ r3.l;
 
16984           s0.h = r1.h ^ r2.h ^ r3.h;
 
16986           int64add4(W[j], s1, W[j-7], s0, W[j-16]);
 
16989         for (j = 0; j < 80; j+=1) {
 
16991           Ch.l = (e.l & f.l) ^ (~e.l & g.l);
 
16992           Ch.h = (e.h & f.h) ^ (~e.h & g.h);
 
16995           int64rrot(r1, e, 14);
 
16996           int64rrot(r2, e, 18);
 
16997           int64revrrot(r3, e, 9);
 
16998           s1.l = r1.l ^ r2.l ^ r3.l;
 
16999           s1.h = r1.h ^ r2.h ^ r3.h;
 
17002           int64rrot(r1, a, 28);
 
17003           int64revrrot(r2, a, 2);
 
17004           int64revrrot(r3, a, 7);
 
17005           s0.l = r1.l ^ r2.l ^ r3.l;
 
17006           s0.h = r1.h ^ r2.h ^ r3.h;
 
17009           Maj.l = (a.l & b.l) ^ (a.l & c.l) ^ (b.l & c.l);
 
17010           Maj.h = (a.h & b.h) ^ (a.h & c.h) ^ (b.h & c.h);
 
17012           int64add5(T1, h, s1, Ch, sha512_k[j], W[j]);
 
17013           int64add(T2, s0, Maj);
 
17018           int64add(e, d, T1);
 
17022           int64add(a, T1, T2);
 
17024         int64add(H[0], H[0], a);
 
17025         int64add(H[1], H[1], b);
 
17026         int64add(H[2], H[2], c);
 
17027         int64add(H[3], H[3], d);
 
17028         int64add(H[4], H[4], e);
 
17029         int64add(H[5], H[5], f);
 
17030         int64add(H[6], H[6], g);
 
17031         int64add(H[7], H[7], h);
 
17034       //represent the hash as an array of 32-bit dwords
 
17035       for (i=0; i<8; i+=1) {
 
17036         hash[2*i] = H[i].h;
 
17037         hash[2*i + 1] = H[i].l;
 
17042     //A constructor for 64-bit numbers
 
17043     function int64(h, l) {
 
17046       //this.toString = int64toString;
 
17049     //Copies src into dst, assuming both are 64-bit numbers
 
17050     function int64copy(dst, src) {
 
17055     //Right-rotates a 64-bit number by shift
 
17056     //Won't handle cases of shift>=32
 
17057     //The function revrrot() is for that
 
17058     function int64rrot(dst, x, shift) {
 
17059       dst.l = (x.l >>> shift) | (x.h << (32-shift));
 
17060       dst.h = (x.h >>> shift) | (x.l << (32-shift));
 
17063     //Reverses the dwords of the source and then rotates right by shift.
 
17064     //This is equivalent to rotation by 32+shift
 
17065     function int64revrrot(dst, x, shift) {
 
17066       dst.l = (x.h >>> shift) | (x.l << (32-shift));
 
17067       dst.h = (x.l >>> shift) | (x.h << (32-shift));
 
17070     //Bitwise-shifts right a 64-bit number by shift
 
17071     //Won't handle shift>=32, but it's never needed in SHA512
 
17072     function int64shr(dst, x, shift) {
 
17073       dst.l = (x.l >>> shift) | (x.h << (32-shift));
 
17074       dst.h = (x.h >>> shift);
 
17077     //Adds two 64-bit numbers
 
17078     //Like the original implementation, does not rely on 32-bit operations
 
17079     function int64add(dst, x, y) {
 
17080        var w0 = (x.l & 0xffff) + (y.l & 0xffff);
 
17081        var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16);
 
17082        var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16);
 
17083        var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16);
 
17084        dst.l = (w0 & 0xffff) | (w1 << 16);
 
17085        dst.h = (w2 & 0xffff) | (w3 << 16);
 
17088     //Same, except with 4 addends. Works faster than adding them one by one.
 
17089     function int64add4(dst, a, b, c, d) {
 
17090        var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff);
 
17091        var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16);
 
17092        var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16);
 
17093        var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16);
 
17094        dst.l = (w0 & 0xffff) | (w1 << 16);
 
17095        dst.h = (w2 & 0xffff) | (w3 << 16);
 
17098     //Same, except with 5 addends
 
17099     function int64add5(dst, a, b, c, d, e) {
 
17100       var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff),
 
17101           w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16),
 
17102           w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16),
 
17103           w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16);
 
17104        dst.l = (w0 & 0xffff) | (w1 << 16);
 
17105        dst.h = (w2 & 0xffff) | (w3 << 16);
 
17109    * @class Hashes.RMD160
 
17111    * @param {Object} [config]
 
17113    * A JavaScript implementation of the RIPEMD-160 Algorithm
 
17114    * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009.
 
17115    * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
 
17116    * See http://pajhome.org.uk/crypt/md5 for details.
 
17117    * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/
 
17119   RMD160 : function (options) {
 
17121      * Private properties configuration variables. You may need to tweak these to be compatible with
 
17122      * the server-side, but the defaults work in most cases.
 
17123      * @see this.setUpperCase() method
 
17124      * @see this.setPad() method
 
17126     var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false,   /* hexadecimal output case format. false - lowercase; true - uppercase  */
 
17127         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',  /* base-64 pad character. Default '=' for strict RFC compliance   */
 
17128         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true, /* enable/disable utf8 encoding */
 
17130            0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15,
 
17131            7,  4, 13,  1, 10,  6, 15,  3, 12,  0,  9,  5,  2, 14, 11,  8,
 
17132            3, 10, 14,  4,  9, 15,  8,  1,  2,  7,  0,  6, 13, 11,  5, 12,
 
17133            1,  9, 11, 10,  0,  8, 12,  4, 13,  3,  7, 15, 14,  5,  6,  2,
 
17134            4,  0,  5,  9,  7, 12,  2, 10, 14,  1,  3,  8, 11,  6, 15, 13
 
17137            5, 14,  7,  0,  9,  2, 11,  4, 13,  6, 15,  8,  1, 10,  3, 12,
 
17138            6, 11,  3,  7,  0, 13,  5, 10, 14, 15,  8, 12,  4,  9,  1,  2,
 
17139           15,  5,  1,  3,  7, 14,  6,  9, 11,  8, 12,  2, 10,  0,  4, 13,
 
17140            8,  6,  4,  1,  3, 11, 15,  0,  5, 12,  2, 13,  9,  7, 10, 14,
 
17141           12, 15, 10,  4,  1,  5,  8,  7,  6,  2, 13, 14,  0,  3,  9, 11
 
17144           11, 14, 15, 12,  5,  8,  7,  9, 11, 13, 14, 15,  6,  7,  9,  8,
 
17145            7,  6,  8, 13, 11,  9,  7, 15,  7, 12, 15,  9, 11,  7, 13, 12,
 
17146           11, 13,  6,  7, 14,  9, 13, 15, 14,  8, 13,  6,  5, 12,  7,  5,
 
17147           11, 12, 14, 15, 14, 15,  9,  8,  9, 14,  5,  6,  8,  6,  5, 12,
 
17148            9, 15,  5, 11,  6,  8, 13, 12,  5, 12, 13, 14, 11,  8,  5,  6
 
17151            8,  9,  9, 11, 13, 15, 15,  5,  7,  7,  8, 11, 14, 14, 12,  6,
 
17152            9, 13, 15,  7, 12,  8,  9, 11,  7,  7, 12,  7,  6, 15, 13, 11,
 
17153            9,  7, 15, 11,  8,  6,  6, 14, 12, 13,  5, 14, 13, 13,  7,  5,
 
17154           15,  5,  8, 11, 14, 14,  6, 14,  6,  9, 12,  9, 12,  5, 15,  8,
 
17155            8,  5, 12,  9, 12,  5, 14,  6,  8, 13,  6,  5, 15, 13, 11, 11
 
17158     /* privileged (public) methods */
 
17159     this.hex = function (s) {
 
17160       return rstr2hex(rstr(s, utf8));
 
17162     this.b64 = function (s) {
 
17163       return rstr2b64(rstr(s, utf8), b64pad);
 
17165     this.any = function (s, e) {
 
17166       return rstr2any(rstr(s, utf8), e);
 
17168     this.hex_hmac = function (k, d) {
 
17169       return rstr2hex(rstr_hmac(k, d));
 
17171     this.b64_hmac = function (k, d) {
 
17172       return rstr2b64(rstr_hmac(k, d), b64pad);
 
17174     this.any_hmac = function (k, d, e) {
 
17175       return rstr2any(rstr_hmac(k, d), e);
 
17178      * Perform a simple self-test to see if the VM is working
 
17179      * @return {String} Hexadecimal hash sample
 
17182     this.vm_test = function () {
 
17183       return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
 
17186      * @description Enable/disable uppercase hexadecimal returned string
 
17188      * @return {Object} this
 
17191     this.setUpperCase = function (a) {
 
17192       if (typeof a === 'boolean' ) { hexcase = a; }
 
17196      * @description Defines a base64 pad string
 
17197      * @param {string} Pad
 
17198      * @return {Object} this
 
17201     this.setPad = function (a) {
 
17202       if (typeof a !== 'undefined' ) { b64pad = a; }
 
17206      * @description Defines a base64 pad string
 
17208      * @return {Object} this
 
17211     this.setUTF8 = function (a) {
 
17212       if (typeof a === 'boolean') { utf8 = a; }
 
17216     /* private methods */
 
17219      * Calculate the rmd160 of a raw string
 
17222       s = (utf8) ? utf8Encode(s) : s;
 
17223       return binl2rstr(binl(rstr2binl(s), s.length * 8));
 
17227      * Calculate the HMAC-rmd160 of a key and some data (raw strings)
 
17229     function rstr_hmac(key, data) {
 
17230       key = (utf8) ? utf8Encode(key) : key;
 
17231       data = (utf8) ? utf8Encode(data) : data;
 
17233           bkey = rstr2binl(key),
 
17234           ipad = Array(16), opad = Array(16);
 
17236       if (bkey.length > 16) {
 
17237         bkey = binl(bkey, key.length * 8);
 
17240       for (i = 0; i < 16; i+=1) {
 
17241         ipad[i] = bkey[i] ^ 0x36363636;
 
17242         opad[i] = bkey[i] ^ 0x5C5C5C5C;
 
17244       hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
 
17245       return binl2rstr(binl(opad.concat(hash), 512 + 160));
 
17249      * Convert an array of little-endian words to a string
 
17251     function binl2rstr(input) {
 
17252       var i, output = '', l = input.length * 32;
 
17253       for (i = 0; i < l; i += 8) {
 
17254         output += String.fromCharCode((input[i>>5] >>> (i % 32)) & 0xFF);
 
17260      * Calculate the RIPE-MD160 of an array of little-endian words, and a bit length.
 
17262     function binl(x, len) {
 
17269           A1, B1, C1, D1, E1,
 
17270           A2, B2, C2, D2, E2;
 
17272       /* append padding */
 
17273       x[len >> 5] |= 0x80 << (len % 32);
 
17274       x[(((len + 64) >>> 9) << 4) + 14] = len;
 
17277       for (i = 0; i < l; i+=16) {
 
17278         A1 = A2 = h0; B1 = B2 = h1; C1 = C2 = h2; D1 = D2 = h3; E1 = E2 = h4;
 
17279         for (j = 0; j <= 79; j+=1) {
 
17280           T = safe_add(A1, rmd160_f(j, B1, C1, D1));
 
17281           T = safe_add(T, x[i + rmd160_r1[j]]);
 
17282           T = safe_add(T, rmd160_K1(j));
 
17283           T = safe_add(bit_rol(T, rmd160_s1[j]), E1);
 
17284           A1 = E1; E1 = D1; D1 = bit_rol(C1, 10); C1 = B1; B1 = T;
 
17285           T = safe_add(A2, rmd160_f(79-j, B2, C2, D2));
 
17286           T = safe_add(T, x[i + rmd160_r2[j]]);
 
17287           T = safe_add(T, rmd160_K2(j));
 
17288           T = safe_add(bit_rol(T, rmd160_s2[j]), E2);
 
17289           A2 = E2; E2 = D2; D2 = bit_rol(C2, 10); C2 = B2; B2 = T;
 
17292         T = safe_add(h1, safe_add(C1, D2));
 
17293         h1 = safe_add(h2, safe_add(D1, E2));
 
17294         h2 = safe_add(h3, safe_add(E1, A2));
 
17295         h3 = safe_add(h4, safe_add(A1, B2));
 
17296         h4 = safe_add(h0, safe_add(B1, C2));
 
17299       return [h0, h1, h2, h3, h4];
 
17302     // specific algorithm methods
 
17303     function rmd160_f(j, x, y, z) {
 
17304       return ( 0 <= j && j <= 15) ? (x ^ y ^ z) :
 
17305          (16 <= j && j <= 31) ? (x & y) | (~x & z) :
 
17306          (32 <= j && j <= 47) ? (x | ~y) ^ z :
 
17307          (48 <= j && j <= 63) ? (x & z) | (y & ~z) :
 
17308          (64 <= j && j <= 79) ? x ^ (y | ~z) :
 
17309          'rmd160_f: j out of range';
 
17312     function rmd160_K1(j) {
 
17313       return ( 0 <= j && j <= 15) ? 0x00000000 :
 
17314          (16 <= j && j <= 31) ? 0x5a827999 :
 
17315          (32 <= j && j <= 47) ? 0x6ed9eba1 :
 
17316          (48 <= j && j <= 63) ? 0x8f1bbcdc :
 
17317          (64 <= j && j <= 79) ? 0xa953fd4e :
 
17318          'rmd160_K1: j out of range';
 
17321     function rmd160_K2(j){
 
17322       return ( 0 <= j && j <= 15) ? 0x50a28be6 :
 
17323          (16 <= j && j <= 31) ? 0x5c4dd124 :
 
17324          (32 <= j && j <= 47) ? 0x6d703ef3 :
 
17325          (48 <= j && j <= 63) ? 0x7a6d76e9 :
 
17326          (64 <= j && j <= 79) ? 0x00000000 :
 
17327          'rmd160_K2: j out of range';
 
17333   (function( window, undefined ) {
 
17334     var freeExports = false;
 
17335     if (typeof exports === 'object' ) {
 
17336       freeExports = exports;
 
17337       if (exports && typeof global === 'object' && global && global === global.global ) { window = global; }
 
17340     if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {
 
17341       // define as an anonymous module, so, through path mapping, it can be aliased
 
17342       define(function () { return Hashes; });
 
17344     else if ( freeExports ) {
 
17345       // in Node.js or RingoJS v0.8.0+
 
17346       if ( typeof module === 'object' && module && module.exports === freeExports ) {
 
17347         module.exports = Hashes;
 
17349       // in Narwhal or RingoJS v0.7.0-
 
17351         freeExports.Hashes = Hashes;
 
17355       // in a browser or Rhino
 
17356       window.Hashes = Hashes;
 
17362 },{}],2:[function(require,module,exports){
 
17365 var hashes = require('jshashes'),
 
17366     xtend = require('xtend'),
 
17367     sha1 = new hashes.SHA1();
 
17371 ohauth.qsString = function(obj) {
 
17372     return Object.keys(obj).sort().map(function(key) {
 
17373         return ohauth.percentEncode(key) + '=' +
 
17374             ohauth.percentEncode(obj[key]);
 
17378 ohauth.stringQs = function(str) {
 
17379     return str.split('&').reduce(function(obj, pair){
 
17380         var parts = pair.split('=');
 
17381         obj[decodeURIComponent(parts[0])] = (null === parts[1]) ?
 
17382             '' : decodeURIComponent(parts[1]);
 
17387 ohauth.rawxhr = function(method, url, data, headers, callback) {
 
17388     var xhr = new XMLHttpRequest(),
 
17389         twoHundred = /^20\d$/;
 
17390     xhr.onreadystatechange = function() {
 
17391         if (4 == xhr.readyState && 0 !== xhr.status) {
 
17392             if (twoHundred.test(xhr.status)) callback(null, xhr);
 
17393             else return callback(xhr, null);
 
17396     xhr.onerror = function(e) { return callback(e, null); };
 
17397     xhr.open(method, url, true);
 
17398     for (var h in headers) xhr.setRequestHeader(h, headers[h]);
 
17402 ohauth.xhr = function(method, url, auth, data, options, callback) {
 
17403     var headers = (options && options.header) || {
 
17404         'Content-Type': 'application/x-www-form-urlencoded'
 
17406     headers.Authorization = 'OAuth ' + ohauth.authHeader(auth);
 
17407     ohauth.rawxhr(method, url, data, headers, callback);
 
17410 ohauth.nonce = function() {
 
17411     for (var o = ''; o.length < 6;) {
 
17412         o += '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'[Math.floor(Math.random() * 61)];
 
17417 ohauth.authHeader = function(obj) {
 
17418     return Object.keys(obj).sort().map(function(key) {
 
17419         return encodeURIComponent(key) + '="' + encodeURIComponent(obj[key]) + '"';
 
17423 ohauth.timestamp = function() { return ~~((+new Date()) / 1000); };
 
17425 ohauth.percentEncode = function(s) {
 
17426     return encodeURIComponent(s)
 
17427         .replace(/\!/g, '%21').replace(/\'/g, '%27')
 
17428         .replace(/\*/g, '%2A').replace(/\(/g, '%28').replace(/\)/g, '%29');
 
17431 ohauth.baseString = function(method, url, params) {
 
17432     if (params.oauth_signature) delete params.oauth_signature;
 
17435         ohauth.percentEncode(url),
 
17436         ohauth.percentEncode(ohauth.qsString(params))].join('&');
 
17439 ohauth.signature = function(oauth_secret, token_secret, baseString) {
 
17440     return sha1.b64_hmac(
 
17441         ohauth.percentEncode(oauth_secret) + '&' +
 
17442         ohauth.percentEncode(token_secret),
 
17447  * Takes an options object for configuration (consumer_key,
 
17448  * consumer_secret, version, signature_method, token) and returns a
 
17449  * function that generates the Authorization header for given data.
 
17451  * The returned function takes these parameters:
 
17452  * - method: GET/POST/...
 
17453  * - uri: full URI with protocol, port, path and query string
 
17454  * - extra_params: any extra parameters (that are passed in the POST data),
 
17455  *   can be an object or a from-urlencoded string.
 
17457  * Returned function returns full OAuth header with "OAuth" string in it.
 
17460 ohauth.headerGenerator = function(options) {
 
17461     options = options || {};
 
17462     var consumer_key = options.consumer_key || '',
 
17463         consumer_secret = options.consumer_secret || '',
 
17464         signature_method = options.signature_method || 'HMAC-SHA1',
 
17465         version = options.version || '1.0',
 
17466         token = options.token || '';
 
17468     return function(method, uri, extra_params) {
 
17469         method = method.toUpperCase();
 
17470         if (typeof extra_params === 'string' && extra_params.length > 0) {
 
17471             extra_params = ohauth.stringQs(extra_params);
 
17474         var uri_parts = uri.split('?', 2),
 
17475         base_uri = uri_parts[0];
 
17477         var query_params = uri_parts.length === 2 ?
 
17478             ohauth.stringQs(uri_parts[1]) : {};
 
17480         var oauth_params = {
 
17481             oauth_consumer_key: consumer_key,
 
17482             oauth_signature_method: signature_method,
 
17483             oauth_version: version,
 
17484             oauth_timestamp: ohauth.timestamp(),
 
17485             oauth_nonce: ohauth.nonce()
 
17488         if (token) oauth_params.oauth_token = token;
 
17490         var all_params = xtend({}, oauth_params, query_params, extra_params),
 
17491             base_str = ohauth.baseString(method, base_uri, all_params);
 
17493         oauth_params.oauth_signature = ohauth.signature(consumer_secret, token, base_str);
 
17495         return 'OAuth ' + ohauth.authHeader(oauth_params);
 
17499 module.exports = ohauth;
 
17501 },{"jshashes":7,"xtend":4}],6:[function(require,module,exports){
 
17502 module.exports = Object.keys || require('./shim');
 
17505 },{"./shim":8}],8:[function(require,module,exports){
 
17509         // modified from https://github.com/kriskowal/es5-shim
 
17510         var has = Object.prototype.hasOwnProperty,
 
17511                 is = require('is'),
 
17512                 forEach = require('foreach'),
 
17513                 hasDontEnumBug = !({'toString': null}).propertyIsEnumerable('toString'),
 
17520                         "propertyIsEnumerable",
 
17525         keysShim = function keys(object) {
 
17526                 if (!is.object(object) && !is.array(object)) {
 
17527                         throw new TypeError("Object.keys called on a non-object");
 
17530                 var name, theKeys = [];
 
17531                 for (name in object) {
 
17532                         if (has.call(object, name)) {
 
17533                                 theKeys.push(name);
 
17537                 if (hasDontEnumBug) {
 
17538                         forEach(dontEnums, function (dontEnum) {
 
17539                                 if (has.call(object, dontEnum)) {
 
17540                                         theKeys.push(dontEnum);
 
17547         module.exports = keysShim;
 
17551 },{"is":9,"foreach":10}],9:[function(require,module,exports){
 
17555  * the definitive JavaScript type testing library
 
17557  * @copyright 2013 Enrico Marino
 
17561 var objProto = Object.prototype;
 
17562 var owns = objProto.hasOwnProperty;
 
17563 var toString = objProto.toString;
 
17564 var isActualNaN = function (value) {
 
17565   return value !== value;
 
17567 var NON_HOST_TYPES = {
 
17578 var is = module.exports = {};
 
17586  * Test if `value` is a type of `type`.
 
17588  * @param {Mixed} value value to test
 
17589  * @param {String} type type
 
17590  * @return {Boolean} true if `value` is a type of `type`, false otherwise
 
17595 is.type = function (value, type) {
 
17596   return typeof value === type;
 
17601  * Test if `value` is defined.
 
17603  * @param {Mixed} value value to test
 
17604  * @return {Boolean} true if 'value' is defined, false otherwise
 
17608 is.defined = function (value) {
 
17609   return value !== undefined;
 
17614  * Test if `value` is empty.
 
17616  * @param {Mixed} value value to test
 
17617  * @return {Boolean} true if `value` is empty, false otherwise
 
17621 is.empty = function (value) {
 
17622   var type = toString.call(value);
 
17625   if ('[object Array]' === type || '[object Arguments]' === type) {
 
17626     return value.length === 0;
 
17629   if ('[object Object]' === type) {
 
17630     for (key in value) if (owns.call(value, key)) return false;
 
17634   if ('[object String]' === type) {
 
17635     return '' === value;
 
17643  * Test if `value` is equal to `other`.
 
17645  * @param {Mixed} value value to test
 
17646  * @param {Mixed} other value to compare with
 
17647  * @return {Boolean} true if `value` is equal to `other`, false otherwise
 
17650 is.equal = function (value, other) {
 
17651   var type = toString.call(value)
 
17654   if (type !== toString.call(other)) {
 
17658   if ('[object Object]' === type) {
 
17659     for (key in value) {
 
17660       if (!is.equal(value[key], other[key])) {
 
17667   if ('[object Array]' === type) {
 
17668     key = value.length;
 
17669     if (key !== other.length) {
 
17673       if (!is.equal(value[key], other[key])) {
 
17680   if ('[object Function]' === type) {
 
17681     return value.prototype === other.prototype;
 
17684   if ('[object Date]' === type) {
 
17685     return value.getTime() === other.getTime();
 
17688   return value === other;
 
17693  * Test if `value` is hosted by `host`.
 
17695  * @param {Mixed} value to test
 
17696  * @param {Mixed} host host to test with
 
17697  * @return {Boolean} true if `value` is hosted by `host`, false otherwise
 
17701 is.hosted = function (value, host) {
 
17702   var type = typeof host[value];
 
17703   return type === 'object' ? !!host[value] : !NON_HOST_TYPES[type];
 
17708  * Test if `value` is an instance of `constructor`.
 
17710  * @param {Mixed} value value to test
 
17711  * @return {Boolean} true if `value` is an instance of `constructor`
 
17715 is.instance = is['instanceof'] = function (value, constructor) {
 
17716   return value instanceof constructor;
 
17721  * Test if `value` is null.
 
17723  * @param {Mixed} value value to test
 
17724  * @return {Boolean} true if `value` is null, false otherwise
 
17728 is['null'] = function (value) {
 
17729   return value === null;
 
17734  * Test if `value` is undefined.
 
17736  * @param {Mixed} value value to test
 
17737  * @return {Boolean} true if `value` is undefined, false otherwise
 
17741 is.undefined = function (value) {
 
17742   return value === undefined;
 
17751  * Test if `value` is an arguments object.
 
17753  * @param {Mixed} value value to test
 
17754  * @return {Boolean} true if `value` is an arguments object, false otherwise
 
17758 is.arguments = function (value) {
 
17759   var isStandardArguments = '[object Arguments]' === toString.call(value);
 
17760   var isOldArguments = !is.array(value) && is.arraylike(value) && is.object(value) && is.fn(value.callee);
 
17761   return isStandardArguments || isOldArguments;
 
17770  * Test if 'value' is an array.
 
17772  * @param {Mixed} value value to test
 
17773  * @return {Boolean} true if `value` is an array, false otherwise
 
17777 is.array = function (value) {
 
17778   return '[object Array]' === toString.call(value);
 
17782  * is.arguments.empty
 
17783  * Test if `value` is an empty arguments object.
 
17785  * @param {Mixed} value value to test
 
17786  * @return {Boolean} true if `value` is an empty arguments object, false otherwise
 
17789 is.arguments.empty = function (value) {
 
17790   return is.arguments(value) && value.length === 0;
 
17795  * Test if `value` is an empty array.
 
17797  * @param {Mixed} value value to test
 
17798  * @return {Boolean} true if `value` is an empty array, false otherwise
 
17801 is.array.empty = function (value) {
 
17802   return is.array(value) && value.length === 0;
 
17807  * Test if `value` is an arraylike object.
 
17809  * @param {Mixed} value value to test
 
17810  * @return {Boolean} true if `value` is an arguments object, false otherwise
 
17814 is.arraylike = function (value) {
 
17815   return !!value && !is.boolean(value)
 
17816     && owns.call(value, 'length')
 
17817     && isFinite(value.length)
 
17818     && is.number(value.length)
 
17819     && value.length >= 0;
 
17828  * Test if `value` is a boolean.
 
17830  * @param {Mixed} value value to test
 
17831  * @return {Boolean} true if `value` is a boolean, false otherwise
 
17835 is.boolean = function (value) {
 
17836   return '[object Boolean]' === toString.call(value);
 
17841  * Test if `value` is false.
 
17843  * @param {Mixed} value value to test
 
17844  * @return {Boolean} true if `value` is false, false otherwise
 
17848 is['false'] = function (value) {
 
17849   return is.boolean(value) && (value === false || value.valueOf() === false);
 
17854  * Test if `value` is true.
 
17856  * @param {Mixed} value value to test
 
17857  * @return {Boolean} true if `value` is true, false otherwise
 
17861 is['true'] = function (value) {
 
17862   return is.boolean(value) && (value === true || value.valueOf() === true);
 
17871  * Test if `value` is a date.
 
17873  * @param {Mixed} value value to test
 
17874  * @return {Boolean} true if `value` is a date, false otherwise
 
17878 is.date = function (value) {
 
17879   return '[object Date]' === toString.call(value);
 
17888  * Test if `value` is an html element.
 
17890  * @param {Mixed} value value to test
 
17891  * @return {Boolean} true if `value` is an HTML Element, false otherwise
 
17895 is.element = function (value) {
 
17896   return value !== undefined
 
17897     && typeof HTMLElement !== 'undefined'
 
17898     && value instanceof HTMLElement
 
17899     && value.nodeType === 1;
 
17908  * Test if `value` is an error object.
 
17910  * @param {Mixed} value value to test
 
17911  * @return {Boolean} true if `value` is an error object, false otherwise
 
17915 is.error = function (value) {
 
17916   return '[object Error]' === toString.call(value);
 
17924  * is.fn / is.function (deprecated)
 
17925  * Test if `value` is a function.
 
17927  * @param {Mixed} value value to test
 
17928  * @return {Boolean} true if `value` is a function, false otherwise
 
17932 is.fn = is['function'] = function (value) {
 
17933   var isAlert = typeof window !== 'undefined' && value === window.alert;
 
17934   return isAlert || '[object Function]' === toString.call(value);
 
17943  * Test if `value` is a number.
 
17945  * @param {Mixed} value value to test
 
17946  * @return {Boolean} true if `value` is a number, false otherwise
 
17950 is.number = function (value) {
 
17951   return '[object Number]' === toString.call(value);
 
17956  * Test if `value` is positive or negative infinity.
 
17958  * @param {Mixed} value value to test
 
17959  * @return {Boolean} true if `value` is positive or negative Infinity, false otherwise
 
17962 is.infinite = function (value) {
 
17963   return value === Infinity || value === -Infinity;
 
17968  * Test if `value` is a decimal number.
 
17970  * @param {Mixed} value value to test
 
17971  * @return {Boolean} true if `value` is a decimal number, false otherwise
 
17975 is.decimal = function (value) {
 
17976   return is.number(value) && !isActualNaN(value) && value % 1 !== 0;
 
17981  * Test if `value` is divisible by `n`.
 
17983  * @param {Number} value value to test
 
17984  * @param {Number} n dividend
 
17985  * @return {Boolean} true if `value` is divisible by `n`, false otherwise
 
17989 is.divisibleBy = function (value, n) {
 
17990   var isDividendInfinite = is.infinite(value);
 
17991   var isDivisorInfinite = is.infinite(n);
 
17992   var isNonZeroNumber = is.number(value) && !isActualNaN(value) && is.number(n) && !isActualNaN(n) && n !== 0;
 
17993   return isDividendInfinite || isDivisorInfinite || (isNonZeroNumber && value % n === 0);
 
17998  * Test if `value` is an integer.
 
18000  * @param value to test
 
18001  * @return {Boolean} true if `value` is an integer, false otherwise
 
18005 is.int = function (value) {
 
18006   return is.number(value) && !isActualNaN(value) && value % 1 === 0;
 
18011  * Test if `value` is greater than 'others' values.
 
18013  * @param {Number} value value to test
 
18014  * @param {Array} others values to compare with
 
18015  * @return {Boolean} true if `value` is greater than `others` values
 
18019 is.maximum = function (value, others) {
 
18020   if (isActualNaN(value)) {
 
18021     throw new TypeError('NaN is not a valid value');
 
18022   } else if (!is.arraylike(others)) {
 
18023     throw new TypeError('second argument must be array-like');
 
18025   var len = others.length;
 
18027   while (--len >= 0) {
 
18028     if (value < others[len]) {
 
18038  * Test if `value` is less than `others` values.
 
18040  * @param {Number} value value to test
 
18041  * @param {Array} others values to compare with
 
18042  * @return {Boolean} true if `value` is less than `others` values
 
18046 is.minimum = function (value, others) {
 
18047   if (isActualNaN(value)) {
 
18048     throw new TypeError('NaN is not a valid value');
 
18049   } else if (!is.arraylike(others)) {
 
18050     throw new TypeError('second argument must be array-like');
 
18052   var len = others.length;
 
18054   while (--len >= 0) {
 
18055     if (value > others[len]) {
 
18065  * Test if `value` is not a number.
 
18067  * @param {Mixed} value value to test
 
18068  * @return {Boolean} true if `value` is not a number, false otherwise
 
18072 is.nan = function (value) {
 
18073   return !is.number(value) || value !== value;
 
18078  * Test if `value` is an even number.
 
18080  * @param {Number} value value to test
 
18081  * @return {Boolean} true if `value` is an even number, false otherwise
 
18085 is.even = function (value) {
 
18086   return is.infinite(value) || (is.number(value) && value === value && value % 2 === 0);
 
18091  * Test if `value` is an odd number.
 
18093  * @param {Number} value value to test
 
18094  * @return {Boolean} true if `value` is an odd number, false otherwise
 
18098 is.odd = function (value) {
 
18099   return is.infinite(value) || (is.number(value) && value === value && value % 2 !== 0);
 
18104  * Test if `value` is greater than or equal to `other`.
 
18106  * @param {Number} value value to test
 
18107  * @param {Number} other value to compare with
 
18108  * @return {Boolean}
 
18112 is.ge = function (value, other) {
 
18113   if (isActualNaN(value) || isActualNaN(other)) {
 
18114     throw new TypeError('NaN is not a valid value');
 
18116   return !is.infinite(value) && !is.infinite(other) && value >= other;
 
18121  * Test if `value` is greater than `other`.
 
18123  * @param {Number} value value to test
 
18124  * @param {Number} other value to compare with
 
18125  * @return {Boolean}
 
18129 is.gt = function (value, other) {
 
18130   if (isActualNaN(value) || isActualNaN(other)) {
 
18131     throw new TypeError('NaN is not a valid value');
 
18133   return !is.infinite(value) && !is.infinite(other) && value > other;
 
18138  * Test if `value` is less than or equal to `other`.
 
18140  * @param {Number} value value to test
 
18141  * @param {Number} other value to compare with
 
18142  * @return {Boolean} if 'value' is less than or equal to 'other'
 
18146 is.le = function (value, other) {
 
18147   if (isActualNaN(value) || isActualNaN(other)) {
 
18148     throw new TypeError('NaN is not a valid value');
 
18150   return !is.infinite(value) && !is.infinite(other) && value <= other;
 
18155  * Test if `value` is less than `other`.
 
18157  * @param {Number} value value to test
 
18158  * @param {Number} other value to compare with
 
18159  * @return {Boolean} if `value` is less than `other`
 
18163 is.lt = function (value, other) {
 
18164   if (isActualNaN(value) || isActualNaN(other)) {
 
18165     throw new TypeError('NaN is not a valid value');
 
18167   return !is.infinite(value) && !is.infinite(other) && value < other;
 
18172  * Test if `value` is within `start` and `finish`.
 
18174  * @param {Number} value value to test
 
18175  * @param {Number} start lower bound
 
18176  * @param {Number} finish upper bound
 
18177  * @return {Boolean} true if 'value' is is within 'start' and 'finish'
 
18180 is.within = function (value, start, finish) {
 
18181   if (isActualNaN(value) || isActualNaN(start) || isActualNaN(finish)) {
 
18182     throw new TypeError('NaN is not a valid value');
 
18183   } else if (!is.number(value) || !is.number(start) || !is.number(finish)) {
 
18184     throw new TypeError('all arguments must be numbers');
 
18186   var isAnyInfinite = is.infinite(value) || is.infinite(start) || is.infinite(finish);
 
18187   return isAnyInfinite || (value >= start && value <= finish);
 
18196  * Test if `value` is an object.
 
18198  * @param {Mixed} value value to test
 
18199  * @return {Boolean} true if `value` is an object, false otherwise
 
18203 is.object = function (value) {
 
18204   return value && '[object Object]' === toString.call(value);
 
18209  * Test if `value` is a hash - a plain object literal.
 
18211  * @param {Mixed} value value to test
 
18212  * @return {Boolean} true if `value` is a hash, false otherwise
 
18216 is.hash = function (value) {
 
18217   return is.object(value) && value.constructor === Object && !value.nodeType && !value.setInterval;
 
18226  * Test if `value` is a regular expression.
 
18228  * @param {Mixed} value value to test
 
18229  * @return {Boolean} true if `value` is a regexp, false otherwise
 
18233 is.regexp = function (value) {
 
18234   return '[object RegExp]' === toString.call(value);
 
18243  * Test if `value` is a string.
 
18245  * @param {Mixed} value value to test
 
18246  * @return {Boolean} true if 'value' is a string, false otherwise
 
18250 is.string = function (value) {
 
18251   return '[object String]' === toString.call(value);
 
18255 },{}],10:[function(require,module,exports){
 
18257 var hasOwn = Object.prototype.hasOwnProperty;
 
18258 var toString = Object.prototype.toString;
 
18260 module.exports = function forEach (obj, fn, ctx) {
 
18261     if (toString.call(fn) !== '[object Function]') {
 
18262         throw new TypeError('iterator must be a function');
 
18264     var l = obj.length;
 
18266         for (var i = 0; i < l; i++) {
 
18267             fn.call(ctx, obj[i], i, obj);
 
18270         for (var k in obj) {
 
18271             if (hasOwn.call(obj, k)) {
 
18272                 fn.call(ctx, obj[k], k, obj);
 
18283  (c) 2015, Vladimir Agafonkin
 
18284  RBush, a JavaScript library for high-performance 2D spatial indexing of points and rectangles.
 
18285  https://github.com/mourner/rbush
 
18291 function rbush(maxEntries, format) {
 
18293     // jshint newcap: false, validthis: true
 
18294     if (!(this instanceof rbush)) return new rbush(maxEntries, format);
 
18296     // max entries in a node is 9 by default; min node fill is 40% for best performance
 
18297     this._maxEntries = Math.max(4, maxEntries || 9);
 
18298     this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
 
18301         this._initFormat(format);
 
18307 rbush.prototype = {
 
18310         return this._all(this.data, []);
 
18313     search: function (bbox) {
 
18315         var node = this.data,
 
18317             toBBox = this.toBBox;
 
18319         if (!intersects(bbox, node.bbox)) return result;
 
18321         var nodesToSearch = [],
 
18322             i, len, child, childBBox;
 
18325             for (i = 0, len = node.children.length; i < len; i++) {
 
18327                 child = node.children[i];
 
18328                 childBBox = node.leaf ? toBBox(child) : child.bbox;
 
18330                 if (intersects(bbox, childBBox)) {
 
18331                     if (node.leaf) result.push(child);
 
18332                     else if (contains(bbox, childBBox)) this._all(child, result);
 
18333                     else nodesToSearch.push(child);
 
18336             node = nodesToSearch.pop();
 
18342     collides: function (bbox) {
 
18344         var node = this.data,
 
18345             toBBox = this.toBBox;
 
18347         if (!intersects(bbox, node.bbox)) return false;
 
18349         var nodesToSearch = [],
 
18350             i, len, child, childBBox;
 
18353             for (i = 0, len = node.children.length; i < len; i++) {
 
18355                 child = node.children[i];
 
18356                 childBBox = node.leaf ? toBBox(child) : child.bbox;
 
18358                 if (intersects(bbox, childBBox)) {
 
18359                     if (node.leaf || contains(bbox, childBBox)) return true;
 
18360                     nodesToSearch.push(child);
 
18363             node = nodesToSearch.pop();
 
18369     load: function (data) {
 
18370         if (!(data && data.length)) return this;
 
18372         if (data.length < this._minEntries) {
 
18373             for (var i = 0, len = data.length; i < len; i++) {
 
18374                 this.insert(data[i]);
 
18379         // recursively build the tree with the given data from stratch using OMT algorithm
 
18380         var node = this._build(data.slice(), 0, data.length - 1, 0);
 
18382         if (!this.data.children.length) {
 
18383             // save as is if tree is empty
 
18386         } else if (this.data.height === node.height) {
 
18387             // split root if trees have the same height
 
18388             this._splitRoot(this.data, node);
 
18391             if (this.data.height < node.height) {
 
18392                 // swap trees if inserted one is bigger
 
18393                 var tmpNode = this.data;
 
18398             // insert the small tree into the large tree at appropriate level
 
18399             this._insert(node, this.data.height - node.height - 1, true);
 
18405     insert: function (item) {
 
18406         if (item) this._insert(item, this.data.height - 1);
 
18410     clear: function () {
 
18420     remove: function (item) {
 
18421         if (!item) return this;
 
18423         var node = this.data,
 
18424             bbox = this.toBBox(item),
 
18427             i, parent, index, goingUp;
 
18429         // depth-first iterative tree traversal
 
18430         while (node || path.length) {
 
18432             if (!node) { // go up
 
18434                 parent = path[path.length - 1];
 
18439             if (node.leaf) { // check current node
 
18440                 index = node.children.indexOf(item);
 
18442                 if (index !== -1) {
 
18443                     // item found, remove the item and condense tree upwards
 
18444                     node.children.splice(index, 1);
 
18446                     this._condense(path);
 
18451             if (!goingUp && !node.leaf && contains(node.bbox, bbox)) { // go down
 
18456                 node = node.children[0];
 
18458             } else if (parent) { // go right
 
18460                 node = parent.children[i];
 
18463             } else node = null; // nothing found
 
18469     toBBox: function (item) { return item; },
 
18471     compareMinX: function (a, b) { return a[0] - b[0]; },
 
18472     compareMinY: function (a, b) { return a[1] - b[1]; },
 
18474     toJSON: function () { return this.data; },
 
18476     fromJSON: function (data) {
 
18481     _all: function (node, result) {
 
18482         var nodesToSearch = [];
 
18484             if (node.leaf) result.push.apply(result, node.children);
 
18485             else nodesToSearch.push.apply(nodesToSearch, node.children);
 
18487             node = nodesToSearch.pop();
 
18492     _build: function (items, left, right, height) {
 
18494         var N = right - left + 1,
 
18495             M = this._maxEntries,
 
18499             // reached leaf level; return leaf
 
18501                 children: items.slice(left, right + 1),
 
18506             calcBBox(node, this.toBBox);
 
18511             // target height of the bulk-loaded tree
 
18512             height = Math.ceil(Math.log(N) / Math.log(M));
 
18514             // target number of root entries to maximize storage utilization
 
18515             M = Math.ceil(N / Math.pow(M, height - 1));
 
18525         // split the items into M mostly square tiles
 
18527         var N2 = Math.ceil(N / M),
 
18528             N1 = N2 * Math.ceil(Math.sqrt(M)),
 
18529             i, j, right2, right3;
 
18531         multiSelect(items, left, right, N1, this.compareMinX);
 
18533         for (i = left; i <= right; i += N1) {
 
18535             right2 = Math.min(i + N1 - 1, right);
 
18537             multiSelect(items, i, right2, N2, this.compareMinY);
 
18539             for (j = i; j <= right2; j += N2) {
 
18541                 right3 = Math.min(j + N2 - 1, right2);
 
18543                 // pack each entry recursively
 
18544                 node.children.push(this._build(items, j, right3, height - 1));
 
18548         calcBBox(node, this.toBBox);
 
18553     _chooseSubtree: function (bbox, node, level, path) {
 
18555         var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;
 
18560             if (node.leaf || path.length - 1 === level) break;
 
18562             minArea = minEnlargement = Infinity;
 
18564             for (i = 0, len = node.children.length; i < len; i++) {
 
18565                 child = node.children[i];
 
18566                 area = bboxArea(child.bbox);
 
18567                 enlargement = enlargedArea(bbox, child.bbox) - area;
 
18569                 // choose entry with the least area enlargement
 
18570                 if (enlargement < minEnlargement) {
 
18571                     minEnlargement = enlargement;
 
18572                     minArea = area < minArea ? area : minArea;
 
18573                     targetNode = child;
 
18575                 } else if (enlargement === minEnlargement) {
 
18576                     // otherwise choose one with the smallest area
 
18577                     if (area < minArea) {
 
18579                         targetNode = child;
 
18590     _insert: function (item, level, isNode) {
 
18592         var toBBox = this.toBBox,
 
18593             bbox = isNode ? item.bbox : toBBox(item),
 
18596         // find the best node for accommodating the item, saving all nodes along the path too
 
18597         var node = this._chooseSubtree(bbox, this.data, level, insertPath);
 
18599         // put the item into the node
 
18600         node.children.push(item);
 
18601         extend(node.bbox, bbox);
 
18603         // split on node overflow; propagate upwards if necessary
 
18604         while (level >= 0) {
 
18605             if (insertPath[level].children.length > this._maxEntries) {
 
18606                 this._split(insertPath, level);
 
18611         // adjust bboxes along the insertion path
 
18612         this._adjustParentBBoxes(bbox, insertPath, level);
 
18615     // split overflowed node into two
 
18616     _split: function (insertPath, level) {
 
18618         var node = insertPath[level],
 
18619             M = node.children.length,
 
18620             m = this._minEntries;
 
18622         this._chooseSplitAxis(node, m, M);
 
18624         var splitIndex = this._chooseSplitIndex(node, m, M);
 
18627             children: node.children.splice(splitIndex, node.children.length - splitIndex),
 
18628             height: node.height,
 
18633         if (node.leaf) newNode.leaf = true;
 
18635         calcBBox(node, this.toBBox);
 
18636         calcBBox(newNode, this.toBBox);
 
18638         if (level) insertPath[level - 1].children.push(newNode);
 
18639         else this._splitRoot(node, newNode);
 
18642     _splitRoot: function (node, newNode) {
 
18645             children: [node, newNode],
 
18646             height: node.height + 1,
 
18650         calcBBox(this.data, this.toBBox);
 
18653     _chooseSplitIndex: function (node, m, M) {
 
18655         var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;
 
18657         minOverlap = minArea = Infinity;
 
18659         for (i = m; i <= M - m; i++) {
 
18660             bbox1 = distBBox(node, 0, i, this.toBBox);
 
18661             bbox2 = distBBox(node, i, M, this.toBBox);
 
18663             overlap = intersectionArea(bbox1, bbox2);
 
18664             area = bboxArea(bbox1) + bboxArea(bbox2);
 
18666             // choose distribution with minimum overlap
 
18667             if (overlap < minOverlap) {
 
18668                 minOverlap = overlap;
 
18671                 minArea = area < minArea ? area : minArea;
 
18673             } else if (overlap === minOverlap) {
 
18674                 // otherwise choose distribution with minimum area
 
18675                 if (area < minArea) {
 
18685     // sorts node children by the best axis for split
 
18686     _chooseSplitAxis: function (node, m, M) {
 
18688         var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX,
 
18689             compareMinY = node.leaf ? this.compareMinY : compareNodeMinY,
 
18690             xMargin = this._allDistMargin(node, m, M, compareMinX),
 
18691             yMargin = this._allDistMargin(node, m, M, compareMinY);
 
18693         // if total distributions margin value is minimal for x, sort by minX,
 
18694         // otherwise it's already sorted by minY
 
18695         if (xMargin < yMargin) node.children.sort(compareMinX);
 
18698     // total margin of all possible split distributions where each node is at least m full
 
18699     _allDistMargin: function (node, m, M, compare) {
 
18701         node.children.sort(compare);
 
18703         var toBBox = this.toBBox,
 
18704             leftBBox = distBBox(node, 0, m, toBBox),
 
18705             rightBBox = distBBox(node, M - m, M, toBBox),
 
18706             margin = bboxMargin(leftBBox) + bboxMargin(rightBBox),
 
18709         for (i = m; i < M - m; i++) {
 
18710             child = node.children[i];
 
18711             extend(leftBBox, node.leaf ? toBBox(child) : child.bbox);
 
18712             margin += bboxMargin(leftBBox);
 
18715         for (i = M - m - 1; i >= m; i--) {
 
18716             child = node.children[i];
 
18717             extend(rightBBox, node.leaf ? toBBox(child) : child.bbox);
 
18718             margin += bboxMargin(rightBBox);
 
18724     _adjustParentBBoxes: function (bbox, path, level) {
 
18725         // adjust bboxes along the given tree path
 
18726         for (var i = level; i >= 0; i--) {
 
18727             extend(path[i].bbox, bbox);
 
18731     _condense: function (path) {
 
18732         // go through the path, removing empty nodes and updating bboxes
 
18733         for (var i = path.length - 1, siblings; i >= 0; i--) {
 
18734             if (path[i].children.length === 0) {
 
18736                     siblings = path[i - 1].children;
 
18737                     siblings.splice(siblings.indexOf(path[i]), 1);
 
18739                 } else this.clear();
 
18741             } else calcBBox(path[i], this.toBBox);
 
18745     _initFormat: function (format) {
 
18746         // data format (minX, minY, maxX, maxY accessors)
 
18748         // uses eval-type function compilation instead of just accepting a toBBox function
 
18749         // because the algorithms are very sensitive to sorting functions performance,
 
18750         // so they should be dead simple and without inner calls
 
18752         // jshint evil: true
 
18754         var compareArr = ['return a', ' - b', ';'];
 
18756         this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
 
18757         this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));
 
18759         this.toBBox = new Function('a', 'return [a' + format.join(', a') + '];');
 
18764 // calculate node's bbox from bboxes of its children
 
18765 function calcBBox(node, toBBox) {
 
18766     node.bbox = distBBox(node, 0, node.children.length, toBBox);
 
18769 // min bounding rectangle of node children from k to p-1
 
18770 function distBBox(node, k, p, toBBox) {
 
18771     var bbox = empty();
 
18773     for (var i = k, child; i < p; i++) {
 
18774         child = node.children[i];
 
18775         extend(bbox, node.leaf ? toBBox(child) : child.bbox);
 
18781 function empty() { return [Infinity, Infinity, -Infinity, -Infinity]; }
 
18783 function extend(a, b) {
 
18784     a[0] = Math.min(a[0], b[0]);
 
18785     a[1] = Math.min(a[1], b[1]);
 
18786     a[2] = Math.max(a[2], b[2]);
 
18787     a[3] = Math.max(a[3], b[3]);
 
18791 function compareNodeMinX(a, b) { return a.bbox[0] - b.bbox[0]; }
 
18792 function compareNodeMinY(a, b) { return a.bbox[1] - b.bbox[1]; }
 
18794 function bboxArea(a)   { return (a[2] - a[0]) * (a[3] - a[1]); }
 
18795 function bboxMargin(a) { return (a[2] - a[0]) + (a[3] - a[1]); }
 
18797 function enlargedArea(a, b) {
 
18798     return (Math.max(b[2], a[2]) - Math.min(b[0], a[0])) *
 
18799            (Math.max(b[3], a[3]) - Math.min(b[1], a[1]));
 
18802 function intersectionArea(a, b) {
 
18803     var minX = Math.max(a[0], b[0]),
 
18804         minY = Math.max(a[1], b[1]),
 
18805         maxX = Math.min(a[2], b[2]),
 
18806         maxY = Math.min(a[3], b[3]);
 
18808     return Math.max(0, maxX - minX) *
 
18809            Math.max(0, maxY - minY);
 
18812 function contains(a, b) {
 
18813     return a[0] <= b[0] &&
 
18819 function intersects(a, b) {
 
18820     return b[0] <= a[2] &&
 
18826 // sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
 
18827 // combines selection algorithm with binary divide & conquer approach
 
18829 function multiSelect(arr, left, right, n, compare) {
 
18830     var stack = [left, right],
 
18833     while (stack.length) {
 
18834         right = stack.pop();
 
18835         left = stack.pop();
 
18837         if (right - left <= n) continue;
 
18839         mid = left + Math.ceil((right - left) / n / 2) * n;
 
18840         select(arr, left, right, mid, compare);
 
18842         stack.push(left, mid, mid, right);
 
18846 // Floyd-Rivest selection algorithm:
 
18847 // sort an array between left and right (inclusive) so that the smallest k elements come first (unordered)
 
18848 function select(arr, left, right, k, compare) {
 
18849     var n, i, z, s, sd, newLeft, newRight, t, j;
 
18851     while (right > left) {
 
18852         if (right - left > 600) {
 
18853             n = right - left + 1;
 
18856             s = 0.5 * Math.exp(2 * z / 3);
 
18857             sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (i - n / 2 < 0 ? -1 : 1);
 
18858             newLeft = Math.max(left, Math.floor(k - i * s / n + sd));
 
18859             newRight = Math.min(right, Math.floor(k + (n - i) * s / n + sd));
 
18860             select(arr, newLeft, newRight, k, compare);
 
18867         swap(arr, left, k);
 
18868         if (compare(arr[right], t) > 0) swap(arr, left, right);
 
18874             while (compare(arr[i], t) < 0) i++;
 
18875             while (compare(arr[j], t) > 0) j--;
 
18878         if (compare(arr[left], t) === 0) swap(arr, left, j);
 
18881             swap(arr, j, right);
 
18884         if (j <= k) left = j + 1;
 
18885         if (k <= j) right = j - 1;
 
18889 function swap(arr, i, j) {
 
18896 // export as AMD/CommonJS module or global variable
 
18897 if (typeof define === 'function' && define.amd) define('rbush', function () { return rbush; });
 
18898 else if (typeof module !== 'undefined') module.exports = rbush;
 
18899 else if (typeof self !== 'undefined') self.rbush = rbush;
 
18900 else window.rbush = rbush;
 
18903 (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;
 
18904 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){
 
18905 module.exports = element;
 
18906 module.exports.pair = pair;
 
18907 module.exports.format = format;
 
18908 module.exports.formatPair = formatPair;
 
18910 function element(x, dims) {
 
18911     return search(x, dims).val;
 
18914 function formatPair(x) {
 
18915     return format(x.lat, 'lat') + ' ' + format(x.lon, 'lon');
 
18918 // Is 0 North or South?
 
18919 function format(x, dim) {
 
18924         dir = dirs[x >= 0 ? 0 : 1],
 
18926         whole = Math.floor(abs),
 
18927         fraction = abs - whole,
 
18928         fractionMinutes = fraction * 60,
 
18929         minutes = Math.floor(fractionMinutes),
 
18930         seconds = Math.floor((fractionMinutes - minutes) * 60);
 
18932     return whole + '° ' +
 
18933         (minutes ? minutes + "' " : '') +
 
18934         (seconds ? seconds + '" ' : '') + dir;
 
18937 function search(x, dims, r) {
 
18938     if (!dims) dims = 'NSEW';
 
18939     if (typeof x !== 'string') return { val: null, regex: r };
 
18940     r = r || /[\s\,]*([\-|\—|\―]?[0-9.]+)°? *(?:([0-9.]+)['’′‘] *)?(?:([0-9.]+)(?:''|"|”|″) *)?([NSEW])?/gi;
 
18942     if (!m) return { val: null, regex: r };
 
18943     else if (m[4] && dims.indexOf(m[4]) === -1) return { val: null, regex: r };
 
18945         val: (((m[1]) ? parseFloat(m[1]) : 0) +
 
18946             ((m[2] ? parseFloat(m[2]) / 60 : 0)) +
 
18947             ((m[3] ? parseFloat(m[3]) / 3600 : 0))) *
 
18948             ((m[4] && m[4] === 'S' || m[4] === 'W') ? -1 : 1),
 
18955 function pair(x, dims) {
 
18957     var one = search(x, dims);
 
18958     if (one.val === null) return null;
 
18959     var two = search(x, dims, one.regex);
 
18960     if (two.val === null) return null;
 
18961     // null if one/two are not contiguous.
 
18962     if (one.raw + two.raw !== x) return null;
 
18963     if (one.dim) return swapdim(one.val, two.val, one.dim);
 
18964     else return [one.val, two.val];
 
18967 function swapdim(a, b, dim) {
 
18968     if (dim == 'N' || dim == 'S') return [a, b];
 
18969     if (dim == 'W' || dim == 'E') return [b, a];
 
18975 ;toGeoJSON = (function() {
 
18978     var removeSpace = (/\s*/g),
 
18979         trimSpace = (/^\s*|\s*$/g),
 
18980         splitSpace = (/\s+/);
 
18981     // generate a short, numeric hash of a string
 
18982     function okhash(x) {
 
18983         if (!x || !x.length) return 0;
 
18984         for (var i = 0, h = 0; i < x.length; i++) {
 
18985             h = ((h << 5) - h) + x.charCodeAt(i) | 0;
 
18988     // all Y children of X
 
18989     function get(x, y) { return x.getElementsByTagName(y); }
 
18990     function attr(x, y) { return x.getAttribute(y); }
 
18991     function attrf(x, y) { return parseFloat(attr(x, y)); }
 
18992     // one Y child of X, if any, otherwise null
 
18993     function get1(x, y) { var n = get(x, y); return n.length ? n[0] : null; }
 
18994     // https://developer.mozilla.org/en-US/docs/Web/API/Node.normalize
 
18995     function norm(el) { if (el.normalize) { el.normalize(); } return el; }
 
18996     // cast array x into numbers
 
18997     function numarray(x) {
 
18998         for (var j = 0, o = []; j < x.length; j++) o[j] = parseFloat(x[j]);
 
19001     function clean(x) {
 
19003         for (var i in x) if (x[i]) o[i] = x[i];
 
19006     // get the content of a text node, if any
 
19007     function nodeVal(x) { if (x) {norm(x);} return x && x.firstChild && x.firstChild.nodeValue; }
 
19008     // get one coordinate from a coordinate array, if any
 
19009     function coord1(v) { return numarray(v.replace(removeSpace, '').split(',')); }
 
19010     // get all coordinates from a coordinate array as [[],[]]
 
19011     function coord(v) {
 
19012         var coords = v.replace(trimSpace, '').split(splitSpace),
 
19014         for (var i = 0; i < coords.length; i++) {
 
19015             o.push(coord1(coords[i]));
 
19019     function coordPair(x) { return [attrf(x, 'lon'), attrf(x, 'lat')]; }
 
19021     // create a new feature collection parent object
 
19024             type: 'FeatureCollection',
 
19029     var styleSupport = false;
 
19030     if (typeof XMLSerializer !== 'undefined') {
 
19031         var serializer = new XMLSerializer();
 
19032         styleSupport = true;
 
19034     function xml2str(str) { return serializer.serializeToString(str); }
 
19037         kml: function(doc, o) {
 
19041                 // styleindex keeps track of hashed styles in order to match features
 
19043                 // atomic geospatial types supported by KML - MultiGeometry is
 
19044                 // handled separately
 
19045                 geotypes = ['Polygon', 'LineString', 'Point', 'Track'],
 
19046                 // all root placemarks in the file
 
19047                 placemarks = get(doc, 'Placemark'),
 
19048                 styles = get(doc, 'Style');
 
19050             if (styleSupport) for (var k = 0; k < styles.length; k++) {
 
19051                 styleIndex['#' + attr(styles[k], 'id')] = okhash(xml2str(styles[k])).toString(16);
 
19053             for (var j = 0; j < placemarks.length; j++) {
 
19054                 gj.features = gj.features.concat(getPlacemark(placemarks[j]));
 
19056             function gxCoord(v) { return numarray(v.split(' ')); }
 
19057             function gxCoords(root) {
 
19058                 var elems = get(root, 'coord', 'gx'), coords = [];
 
19059                 for (var i = 0; i < elems.length; i++) coords.push(gxCoord(nodeVal(elems[i])));
 
19062             function getGeometry(root) {
 
19063                 var geomNode, geomNodes, i, j, k, geoms = [];
 
19064                 if (get1(root, 'MultiGeometry')) return getGeometry(get1(root, 'MultiGeometry'));
 
19065                 if (get1(root, 'MultiTrack')) return getGeometry(get1(root, 'MultiTrack'));
 
19066                 for (i = 0; i < geotypes.length; i++) {
 
19067                     geomNodes = get(root, geotypes[i]);
 
19069                         for (j = 0; j < geomNodes.length; j++) {
 
19070                             geomNode = geomNodes[j];
 
19071                             if (geotypes[i] == 'Point') {
 
19074                                     coordinates: coord1(nodeVal(get1(geomNode, 'coordinates')))
 
19076                             } else if (geotypes[i] == 'LineString') {
 
19078                                     type: 'LineString',
 
19079                                     coordinates: coord(nodeVal(get1(geomNode, 'coordinates')))
 
19081                             } else if (geotypes[i] == 'Polygon') {
 
19082                                 var rings = get(geomNode, 'LinearRing'),
 
19084                                 for (k = 0; k < rings.length; k++) {
 
19085                                     coords.push(coord(nodeVal(get1(rings[k], 'coordinates'))));
 
19089                                     coordinates: coords
 
19091                             } else if (geotypes[i] == 'Track') {
 
19093                                     type: 'LineString',
 
19094                                     coordinates: gxCoords(geomNode)
 
19102             function getPlacemark(root) {
 
19103                 var geoms = getGeometry(root), i, properties = {},
 
19104                     name = nodeVal(get1(root, 'name')),
 
19105                     styleUrl = nodeVal(get1(root, 'styleUrl')),
 
19106                     description = nodeVal(get1(root, 'description')),
 
19107                     extendedData = get1(root, 'ExtendedData');
 
19109                 if (!geoms.length) return [];
 
19110                 if (name) properties.name = name;
 
19111                 if (styleUrl && styleIndex[styleUrl]) {
 
19112                     properties.styleUrl = styleUrl;
 
19113                     properties.styleHash = styleIndex[styleUrl];
 
19115                 if (description) properties.description = description;
 
19116                 if (extendedData) {
 
19117                     var datas = get(extendedData, 'Data'),
 
19118                         simpleDatas = get(extendedData, 'SimpleData');
 
19120                     for (i = 0; i < datas.length; i++) {
 
19121                         properties[datas[i].getAttribute('name')] = nodeVal(get1(datas[i], 'value'));
 
19123                     for (i = 0; i < simpleDatas.length; i++) {
 
19124                         properties[simpleDatas[i].getAttribute('name')] = nodeVal(simpleDatas[i]);
 
19129                     geometry: (geoms.length === 1) ? geoms[0] : {
 
19130                         type: 'GeometryCollection',
 
19133                     properties: properties
 
19138         gpx: function(doc, o) {
 
19140                 tracks = get(doc, 'trk'),
 
19141                 routes = get(doc, 'rte'),
 
19142                 waypoints = get(doc, 'wpt'),
 
19143                 // a feature collection
 
19145             for (i = 0; i < tracks.length; i++) {
 
19146                 gj.features.push(getLinestring(tracks[i], 'trkpt'));
 
19148             for (i = 0; i < routes.length; i++) {
 
19149                 gj.features.push(getLinestring(routes[i], 'rtept'));
 
19151             for (i = 0; i < waypoints.length; i++) {
 
19152                 gj.features.push(getPoint(waypoints[i]));
 
19154             function getLinestring(node, pointname) {
 
19155                 var j, pts = get(node, pointname), line = [];
 
19156                 for (j = 0; j < pts.length; j++) {
 
19157                     line.push(coordPair(pts[j]));
 
19161                     properties: getProperties(node),
 
19163                         type: 'LineString',
 
19168             function getPoint(node) {
 
19169                 var prop = getProperties(node);
 
19170                 prop.ele = nodeVal(get1(node, 'ele'));
 
19171                 prop.sym = nodeVal(get1(node, 'sym'));
 
19177                         coordinates: coordPair(node)
 
19181             function getProperties(node) {
 
19182                 var meta = ['name', 'desc', 'author', 'copyright', 'link',
 
19183                             'time', 'keywords'],
 
19186                 for (k = 0; k < meta.length; k++) {
 
19187                     prop[meta[k]] = nodeVal(get1(node, meta[k]));
 
19189                 return clean(prop);
 
19197 if (typeof module !== 'undefined') module.exports = toGeoJSON;
 
19199  * marked - a markdown parser
 
19200  * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed)
 
19201  * https://github.com/chjj/marked
 
19207  * Block-Level Grammar
 
19212   code: /^( {4}[^\n]+\n*)+/,
 
19214   hr: /^( *[-*_]){3,} *(?:\n+|$)/,
 
19215   heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
 
19217   lheading: /^([^\n]+)\n *(=|-){3,} *\n*/,
 
19218   blockquote: /^( *>[^\n]+(\n[^\n]+)*\n*)+/,
 
19219   list: /^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
 
19220   html: /^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,
 
19221   def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
 
19223   paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
 
19227 block.bullet = /(?:[*+-]|\d+\.)/;
 
19228 block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
 
19229 block.item = replace(block.item, 'gm')
 
19230   (/bull/g, block.bullet)
 
19233 block.list = replace(block.list)
 
19234   (/bull/g, block.bullet)
 
19235   ('hr', /\n+(?=(?: *[-*_]){3,} *(?:\n+|$))/)
 
19238 block._tag = '(?!(?:'
 
19239   + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
 
19240   + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
 
19241   + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|@)\\b';
 
19243 block.html = replace(block.html)
 
19244   ('comment', /<!--[\s\S]*?-->/)
 
19245   ('closed', /<(tag)[\s\S]+?<\/\1>/)
 
19246   ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
 
19247   (/tag/g, block._tag)
 
19250 block.paragraph = replace(block.paragraph)
 
19252   ('heading', block.heading)
 
19253   ('lheading', block.lheading)
 
19254   ('blockquote', block.blockquote)
 
19255   ('tag', '<' + block._tag)
 
19260  * Normal Block Grammar
 
19263 block.normal = merge({}, block);
 
19266  * GFM Block Grammar
 
19269 block.gfm = merge({}, block.normal, {
 
19270   fences: /^ *(`{3,}|~{3,}) *(\S+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,
 
19274 block.gfm.paragraph = replace(block.paragraph)
 
19275   ('(?!', '(?!' + block.gfm.fences.source.replace('\\1', '\\2') + '|')
 
19279  * GFM + Tables Block Grammar
 
19282 block.tables = merge({}, block.gfm, {
 
19283   nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
 
19284   table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
 
19291 function Lexer(options) {
 
19293   this.tokens.links = {};
 
19294   this.options = options || marked.defaults;
 
19295   this.rules = block.normal;
 
19297   if (this.options.gfm) {
 
19298     if (this.options.tables) {
 
19299       this.rules = block.tables;
 
19301       this.rules = block.gfm;
 
19307  * Expose Block Rules
 
19310 Lexer.rules = block;
 
19313  * Static Lex Method
 
19316 Lexer.lex = function(src, options) {
 
19317   var lexer = new Lexer(options);
 
19318   return lexer.lex(src);
 
19325 Lexer.prototype.lex = function(src) {
 
19327     .replace(/\r\n|\r/g, '\n')
 
19328     .replace(/\t/g, '    ')
 
19329     .replace(/\u00a0/g, ' ')
 
19330     .replace(/\u2424/g, '\n');
 
19332   return this.token(src, true);
 
19339 Lexer.prototype.token = function(src, top) {
 
19340   var src = src.replace(/^ +$/gm, '')
 
19353     if (cap = this.rules.newline.exec(src)) {
 
19354       src = src.substring(cap[0].length);
 
19355       if (cap[0].length > 1) {
 
19363     if (cap = this.rules.code.exec(src)) {
 
19364       src = src.substring(cap[0].length);
 
19365       cap = cap[0].replace(/^ {4}/gm, '');
 
19368         text: !this.options.pedantic
 
19369           ? cap.replace(/\n+$/, '')
 
19376     if (cap = this.rules.fences.exec(src)) {
 
19377       src = src.substring(cap[0].length);
 
19387     if (cap = this.rules.heading.exec(src)) {
 
19388       src = src.substring(cap[0].length);
 
19391         depth: cap[1].length,
 
19397     // table no leading pipe (gfm)
 
19398     if (top && (cap = this.rules.nptable.exec(src))) {
 
19399       src = src.substring(cap[0].length);
 
19403         header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
 
19404         align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
 
19405         cells: cap[3].replace(/\n$/, '').split('\n')
 
19408       for (i = 0; i < item.align.length; i++) {
 
19409         if (/^ *-+: *$/.test(item.align[i])) {
 
19410           item.align[i] = 'right';
 
19411         } else if (/^ *:-+: *$/.test(item.align[i])) {
 
19412           item.align[i] = 'center';
 
19413         } else if (/^ *:-+ *$/.test(item.align[i])) {
 
19414           item.align[i] = 'left';
 
19416           item.align[i] = null;
 
19420       for (i = 0; i < item.cells.length; i++) {
 
19421         item.cells[i] = item.cells[i].split(/ *\| */);
 
19424       this.tokens.push(item);
 
19430     if (cap = this.rules.lheading.exec(src)) {
 
19431       src = src.substring(cap[0].length);
 
19434         depth: cap[2] === '=' ? 1 : 2,
 
19441     if (cap = this.rules.hr.exec(src)) {
 
19442       src = src.substring(cap[0].length);
 
19450     if (cap = this.rules.blockquote.exec(src)) {
 
19451       src = src.substring(cap[0].length);
 
19454         type: 'blockquote_start'
 
19457       cap = cap[0].replace(/^ *> ?/gm, '');
 
19459       // Pass `top` to keep the current
 
19460       // "toplevel" state. This is exactly
 
19461       // how markdown.pl works.
 
19462       this.token(cap, top);
 
19465         type: 'blockquote_end'
 
19472     if (cap = this.rules.list.exec(src)) {
 
19473       src = src.substring(cap[0].length);
 
19477         type: 'list_start',
 
19478         ordered: bull.length > 1
 
19481       // Get each top-level item.
 
19482       cap = cap[0].match(this.rules.item);
 
19488       for (; i < l; i++) {
 
19491         // Remove the list item's bullet
 
19492         // so it is seen as the next token.
 
19493         space = item.length;
 
19494         item = item.replace(/^ *([*+-]|\d+\.) +/, '');
 
19496         // Outdent whatever the
 
19497         // list item contains. Hacky.
 
19498         if (~item.indexOf('\n ')) {
 
19499           space -= item.length;
 
19500           item = !this.options.pedantic
 
19501             ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
 
19502             : item.replace(/^ {1,4}/gm, '');
 
19505         // Determine whether the next list item belongs here.
 
19506         // Backpedal if it does not belong in this list.
 
19507         if (this.options.smartLists && i !== l - 1) {
 
19508           b = block.bullet.exec(cap[i+1])[0];
 
19509           if (bull !== b && !(bull.length > 1 && b.length > 1)) {
 
19510             src = cap.slice(i + 1).join('\n') + src;
 
19515         // Determine whether item is loose or not.
 
19516         // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
 
19517         // for discount behavior.
 
19518         loose = next || /\n\n(?!\s*$)/.test(item);
 
19520           next = item[item.length-1] === '\n';
 
19521           if (!loose) loose = next;
 
19526             ? 'loose_item_start'
 
19527             : 'list_item_start'
 
19531         this.token(item, false);
 
19534           type: 'list_item_end'
 
19546     if (cap = this.rules.html.exec(src)) {
 
19547       src = src.substring(cap[0].length);
 
19549         type: this.options.sanitize
 
19552         pre: cap[1] === 'pre' || cap[1] === 'script',
 
19559     if (top && (cap = this.rules.def.exec(src))) {
 
19560       src = src.substring(cap[0].length);
 
19561       this.tokens.links[cap[1].toLowerCase()] = {
 
19569     if (top && (cap = this.rules.table.exec(src))) {
 
19570       src = src.substring(cap[0].length);
 
19574         header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
 
19575         align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
 
19576         cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
 
19579       for (i = 0; i < item.align.length; i++) {
 
19580         if (/^ *-+: *$/.test(item.align[i])) {
 
19581           item.align[i] = 'right';
 
19582         } else if (/^ *:-+: *$/.test(item.align[i])) {
 
19583           item.align[i] = 'center';
 
19584         } else if (/^ *:-+ *$/.test(item.align[i])) {
 
19585           item.align[i] = 'left';
 
19587           item.align[i] = null;
 
19591       for (i = 0; i < item.cells.length; i++) {
 
19592         item.cells[i] = item.cells[i]
 
19593           .replace(/^ *\| *| *\| *$/g, '')
 
19597       this.tokens.push(item);
 
19602     // top-level paragraph
 
19603     if (top && (cap = this.rules.paragraph.exec(src))) {
 
19604       src = src.substring(cap[0].length);
 
19607         text: cap[1][cap[1].length-1] === '\n'
 
19608           ? cap[1].slice(0, -1)
 
19615     if (cap = this.rules.text.exec(src)) {
 
19616       // Top-level should never reach here.
 
19617       src = src.substring(cap[0].length);
 
19627         Error('Infinite loop on byte: ' + src.charCodeAt(0));
 
19631   return this.tokens;
 
19635  * Inline-Level Grammar
 
19639   escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
 
19640   autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
 
19642   tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
 
19643   link: /^!?\[(inside)\]\(href\)/,
 
19644   reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
 
19645   nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
 
19646   strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
 
19647   em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
 
19648   code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
 
19649   br: /^ {2,}\n(?!\s*$)/,
 
19651   text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
 
19654 inline._inside = /(?:\[[^\]]*\]|[^\]]|\](?=[^\[]*\]))*/;
 
19655 inline._href = /\s*<?([^\s]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
 
19657 inline.link = replace(inline.link)
 
19658   ('inside', inline._inside)
 
19659   ('href', inline._href)
 
19662 inline.reflink = replace(inline.reflink)
 
19663   ('inside', inline._inside)
 
19667  * Normal Inline Grammar
 
19670 inline.normal = merge({}, inline);
 
19673  * Pedantic Inline Grammar
 
19676 inline.pedantic = merge({}, inline.normal, {
 
19677   strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
 
19678   em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
 
19682  * GFM Inline Grammar
 
19685 inline.gfm = merge({}, inline.normal, {
 
19686   escape: replace(inline.escape)('])', '~|])')(),
 
19687   url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
 
19688   del: /^~~(?=\S)([\s\S]*?\S)~~/,
 
19689   text: replace(inline.text)
 
19691     ('|', '|https?://|')
 
19696  * GFM + Line Breaks Inline Grammar
 
19699 inline.breaks = merge({}, inline.gfm, {
 
19700   br: replace(inline.br)('{2,}', '*')(),
 
19701   text: replace(inline.gfm.text)('{2,}', '*')()
 
19705  * Inline Lexer & Compiler
 
19708 function InlineLexer(links, options) {
 
19709   this.options = options || marked.defaults;
 
19710   this.links = links;
 
19711   this.rules = inline.normal;
 
19715       Error('Tokens array requires a `links` property.');
 
19718   if (this.options.gfm) {
 
19719     if (this.options.breaks) {
 
19720       this.rules = inline.breaks;
 
19722       this.rules = inline.gfm;
 
19724   } else if (this.options.pedantic) {
 
19725     this.rules = inline.pedantic;
 
19730  * Expose Inline Rules
 
19733 InlineLexer.rules = inline;
 
19736  * Static Lexing/Compiling Method
 
19739 InlineLexer.output = function(src, links, options) {
 
19740   var inline = new InlineLexer(links, options);
 
19741   return inline.output(src);
 
19748 InlineLexer.prototype.output = function(src) {
 
19757     if (cap = this.rules.escape.exec(src)) {
 
19758       src = src.substring(cap[0].length);
 
19764     if (cap = this.rules.autolink.exec(src)) {
 
19765       src = src.substring(cap[0].length);
 
19766       if (cap[2] === '@') {
 
19767         text = cap[1][6] === ':'
 
19768           ? this.mangle(cap[1].substring(7))
 
19769           : this.mangle(cap[1]);
 
19770         href = this.mangle('mailto:') + text;
 
19772         text = escape(cap[1]);
 
19784     if (cap = this.rules.url.exec(src)) {
 
19785       src = src.substring(cap[0].length);
 
19786       text = escape(cap[1]);
 
19797     if (cap = this.rules.tag.exec(src)) {
 
19798       src = src.substring(cap[0].length);
 
19799       out += this.options.sanitize
 
19806     if (cap = this.rules.link.exec(src)) {
 
19807       src = src.substring(cap[0].length);
 
19808       out += this.outputLink(cap, {
 
19816     if ((cap = this.rules.reflink.exec(src))
 
19817         || (cap = this.rules.nolink.exec(src))) {
 
19818       src = src.substring(cap[0].length);
 
19819       link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
 
19820       link = this.links[link.toLowerCase()];
 
19821       if (!link || !link.href) {
 
19823         src = cap[0].substring(1) + src;
 
19826       out += this.outputLink(cap, link);
 
19831     if (cap = this.rules.strong.exec(src)) {
 
19832       src = src.substring(cap[0].length);
 
19834         + this.output(cap[2] || cap[1])
 
19840     if (cap = this.rules.em.exec(src)) {
 
19841       src = src.substring(cap[0].length);
 
19843         + this.output(cap[2] || cap[1])
 
19849     if (cap = this.rules.code.exec(src)) {
 
19850       src = src.substring(cap[0].length);
 
19852         + escape(cap[2], true)
 
19858     if (cap = this.rules.br.exec(src)) {
 
19859       src = src.substring(cap[0].length);
 
19865     if (cap = this.rules.del.exec(src)) {
 
19866       src = src.substring(cap[0].length);
 
19868         + this.output(cap[1])
 
19874     if (cap = this.rules.text.exec(src)) {
 
19875       src = src.substring(cap[0].length);
 
19876       out += escape(cap[0]);
 
19882         Error('Infinite loop on byte: ' + src.charCodeAt(0));
 
19893 InlineLexer.prototype.outputLink = function(cap, link) {
 
19894   if (cap[0][0] !== '!') {
 
19896       + escape(link.href)
 
19900       + escape(link.title)
 
19904       + this.output(cap[1])
 
19907     return '<img src="'
 
19908       + escape(link.href)
 
19914       + escape(link.title)
 
19922  * Smartypants Transformations
 
19925 InlineLexer.prototype.smartypants = function(text) {
 
19926   if (!this.options.smartypants) return text;
 
19928     .replace(/--/g, '—')
 
19929     .replace(/'([^']*)'/g, '‘$1’')
 
19930     .replace(/"([^"]*)"/g, '“$1”')
 
19931     .replace(/\.{3}/g, '…');
 
19938 InlineLexer.prototype.mangle = function(text) {
 
19944   for (; i < l; i++) {
 
19945     ch = text.charCodeAt(i);
 
19946     if (Math.random() > 0.5) {
 
19947       ch = 'x' + ch.toString(16);
 
19949     out += '&#' + ch + ';';
 
19956  * Parsing & Compiling
 
19959 function Parser(options) {
 
19962   this.options = options || marked.defaults;
 
19966  * Static Parse Method
 
19969 Parser.parse = function(src, options) {
 
19970   var parser = new Parser(options);
 
19971   return parser.parse(src);
 
19978 Parser.prototype.parse = function(src) {
 
19979   this.inline = new InlineLexer(src.links, this.options);
 
19980   this.tokens = src.reverse();
 
19983   while (this.next()) {
 
19994 Parser.prototype.next = function() {
 
19995   return this.token = this.tokens.pop();
 
19999  * Preview Next Token
 
20002 Parser.prototype.peek = function() {
 
20003   return this.tokens[this.tokens.length-1] || 0;
 
20007  * Parse Text Tokens
 
20010 Parser.prototype.parseText = function() {
 
20011   var body = this.token.text;
 
20013   while (this.peek().type === 'text') {
 
20014     body += '\n' + this.next().text;
 
20017   return this.inline.output(body);
 
20021  * Parse Current Token
 
20024 Parser.prototype.tok = function() {
 
20025   switch (this.token.type) {
 
20036         + this.inline.output(this.token.text)
 
20042       if (this.options.highlight) {
 
20043         var code = this.options.highlight(this.token.text, this.token.lang);
 
20044         if (code != null && code !== this.token.text) {
 
20045           this.token.escaped = true;
 
20046           this.token.text = code;
 
20050       if (!this.token.escaped) {
 
20051         this.token.text = escape(this.token.text, true);
 
20054       return '<pre><code'
 
20057         + this.options.langPrefix
 
20063         + '</code></pre>\n';
 
20074       body += '<thead>\n<tr>\n';
 
20075       for (i = 0; i < this.token.header.length; i++) {
 
20076         heading = this.inline.output(this.token.header[i]);
 
20077         body += this.token.align[i]
 
20078           ? '<th align="' + this.token.align[i] + '">' + heading + '</th>\n'
 
20079           : '<th>' + heading + '</th>\n';
 
20081       body += '</tr>\n</thead>\n';
 
20084       body += '<tbody>\n'
 
20085       for (i = 0; i < this.token.cells.length; i++) {
 
20086         row = this.token.cells[i];
 
20088         for (j = 0; j < row.length; j++) {
 
20089           cell = this.inline.output(row[j]);
 
20090           body += this.token.align[j]
 
20091             ? '<td align="' + this.token.align[j] + '">' + cell + '</td>\n'
 
20092             : '<td>' + cell + '</td>\n';
 
20096       body += '</tbody>\n';
 
20102     case 'blockquote_start': {
 
20105       while (this.next().type !== 'blockquote_end') {
 
20106         body += this.tok();
 
20109       return '<blockquote>\n'
 
20111         + '</blockquote>\n';
 
20113     case 'list_start': {
 
20114       var type = this.token.ordered ? 'ol' : 'ul'
 
20117       while (this.next().type !== 'list_end') {
 
20118         body += this.tok();
 
20129     case 'list_item_start': {
 
20132       while (this.next().type !== 'list_item_end') {
 
20133         body += this.token.type === 'text'
 
20142     case 'loose_item_start': {
 
20145       while (this.next().type !== 'list_item_end') {
 
20146         body += this.tok();
 
20154       return !this.token.pre && !this.options.pedantic
 
20155         ? this.inline.output(this.token.text)
 
20158     case 'paragraph': {
 
20160         + this.inline.output(this.token.text)
 
20175 function escape(html, encode) {
 
20177     .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&')
 
20178     .replace(/</g, '<')
 
20179     .replace(/>/g, '>')
 
20180     .replace(/"/g, '"')
 
20181     .replace(/'/g, ''');
 
20184 function replace(regex, opt) {
 
20185   regex = regex.source;
 
20187   return function self(name, val) {
 
20188     if (!name) return new RegExp(regex, opt);
 
20189     val = val.source || val;
 
20190     val = val.replace(/(^|[^\[])\^/g, '$1');
 
20191     regex = regex.replace(name, val);
 
20199 function merge(obj) {
 
20204   for (; i < arguments.length; i++) {
 
20205     target = arguments[i];
 
20206     for (key in target) {
 
20207       if (Object.prototype.hasOwnProperty.call(target, key)) {
 
20208         obj[key] = target[key];
 
20220 function marked(src, opt, callback) {
 
20221   if (callback || typeof opt === 'function') {
 
20227     if (opt) opt = merge({}, marked.defaults, opt);
 
20229     var tokens = Lexer.lex(tokens, opt)
 
20230       , highlight = opt.highlight
 
20232       , l = tokens.length
 
20235     if (!highlight || highlight.length < 3) {
 
20236       return callback(null, Parser.parse(tokens, opt));
 
20239     var done = function() {
 
20240       delete opt.highlight;
 
20241       var out = Parser.parse(tokens, opt);
 
20242       opt.highlight = highlight;
 
20243       return callback(null, out);
 
20246     for (; i < l; i++) {
 
20248         if (token.type !== 'code') return;
 
20250         return highlight(token.text, token.lang, function(err, code) {
 
20251           if (code == null || code === token.text) {
 
20252             return --pending || done();
 
20255           token.escaped = true;
 
20256           --pending || done();
 
20264     if (opt) opt = merge({}, marked.defaults, opt);
 
20265     return Parser.parse(Lexer.lex(src, opt), opt);
 
20267     e.message += '\nPlease report this to https://github.com/chjj/marked.';
 
20268     if ((opt || marked.defaults).silent) {
 
20269       return '<p>An error occured:</p><pre>'
 
20270         + escape(e.message + '', true)
 
20282 marked.setOptions = function(opt) {
 
20283   merge(marked.defaults, opt);
 
20287 marked.defaults = {
 
20296   langPrefix: 'lang-'
 
20303 marked.Parser = Parser;
 
20304 marked.parser = Parser.parse;
 
20306 marked.Lexer = Lexer;
 
20307 marked.lexer = Lexer.lex;
 
20309 marked.InlineLexer = InlineLexer;
 
20310 marked.inlineLexer = InlineLexer.output;
 
20312 marked.parse = marked;
 
20314 if (typeof exports === 'object') {
 
20315   module.exports = marked;
 
20316 } else if (typeof define === 'function' && define.amd) {
 
20317   define(function() { return marked; });
 
20319   this.marked = marked;
 
20322 }).call(function() {
 
20323   return this || (typeof window !== 'undefined' ? window : global);
 
20327 window.iD = function () {
 
20328     window.locale.en = iD.data.en;
 
20329     window.locale.current('en');
 
20331     var dispatch = d3.dispatch('enter', 'exit', 'change'),
 
20334     // https://github.com/openstreetmap/iD/issues/772
 
20335     // http://mathiasbynens.be/notes/localstorage-pattern#comment-9
 
20337     try { storage = localStorage; } catch (e) {}  // eslint-disable-line no-empty
 
20338     storage = storage || (function() {
 
20341             getItem: function(k) { return s[k]; },
 
20342             setItem: function(k, v) { s[k] = v; },
 
20343             removeItem: function(k) { delete s[k]; }
 
20347     context.storage = function(k, v) {
 
20349             if (arguments.length === 1) return storage.getItem(k);
 
20350             else if (v === null) storage.removeItem(k);
 
20351             else storage.setItem(k, v);
 
20353             // localstorage quota exceeded
 
20354             /* eslint-disable no-console */
 
20355             if (typeof console !== 'undefined') console.error('localStorage quota exceeded');
 
20356             /* eslint-enable no-console */
 
20361     /* Straight accessors. Avoid using these if you can. */
 
20362     var ui, connection, history;
 
20363     context.ui = function() { return ui; };
 
20364     context.connection = function() { return connection; };
 
20365     context.history = function() { return history; };
 
20369     function entitiesLoaded(err, result) {
 
20370         if (!err) history.merge(result.data, result.extent);
 
20373     context.preauth = function(options) {
 
20374         connection.switch(options);
 
20378     context.loadTiles = function(projection, dimensions, callback) {
 
20379         function done(err, result) {
 
20380             entitiesLoaded(err, result);
 
20381             if (callback) callback(err, result);
 
20383         connection.loadTiles(projection, dimensions, done);
 
20386     context.loadEntity = function(id, callback) {
 
20387         function done(err, result) {
 
20388             entitiesLoaded(err, result);
 
20389             if (callback) callback(err, result);
 
20391         connection.loadEntity(id, done);
 
20394     context.zoomToEntity = function(id, zoomTo) {
 
20395         if (zoomTo !== false) {
 
20396             this.loadEntity(id, function(err, result) {
 
20398                 var entity = _.find(result.data, function(e) { return e.id === id; });
 
20399                 if (entity) { map.zoomTo(entity); }
 
20403         map.on('drawn.zoomToEntity', function() {
 
20404             if (!context.hasEntity(id)) return;
 
20405             map.on('drawn.zoomToEntity', null);
 
20406             context.on('enter.zoomToEntity', null);
 
20407             context.enter(iD.modes.Select(context, [id]));
 
20410         context.on('enter.zoomToEntity', function() {
 
20411             if (mode.id !== 'browse') {
 
20412                 map.on('drawn.zoomToEntity', null);
 
20413                 context.on('enter.zoomToEntity', null);
 
20418     var minEditableZoom = 16;
 
20419     context.minEditableZoom = function(_) {
 
20420         if (!arguments.length) return minEditableZoom;
 
20421         minEditableZoom = _;
 
20422         connection.tileZoom(_);
 
20428     var inIntro = false;
 
20429     context.inIntro = function(_) {
 
20430         if (!arguments.length) return inIntro;
 
20435     context.save = function() {
 
20436         if (inIntro || (mode && mode.id === 'save') || d3.select('.modal').size()) return;
 
20438         if (history.hasChanges()) return t('save.unsaved_changes');
 
20441     context.flush = function() {
 
20442         context.debouncedSave.cancel();
 
20443         connection.flush();
 
20446         _.each(iD.services, function(service) {
 
20447             var reset = service().reset;
 
20448             if (reset) reset(context);
 
20455     context.hasEntity = function(id) {
 
20456         return history.graph().hasEntity(id);
 
20458     context.entity = function(id) {
 
20459         return history.graph().entity(id);
 
20461     context.childNodes = function(way) {
 
20462         return history.graph().childNodes(way);
 
20464     context.geometry = function(id) {
 
20465         return context.entity(id).geometry(history.graph());
 
20471     context.mode = function() {
 
20474     context.enter = function(newMode) {
 
20477             dispatch.exit(mode);
 
20482         dispatch.enter(mode);
 
20485     context.selectedIDs = function() {
 
20486         if (mode && mode.selectedIDs) {
 
20487             return mode.selectedIDs();
 
20495     context.install = function(behavior) {
 
20496         context.surface().call(behavior);
 
20498     context.uninstall = function(behavior) {
 
20499         context.surface().call(behavior.off);
 
20504     var copyIDs = [], copyGraph;
 
20505     context.copyGraph = function() { return copyGraph; };
 
20506     context.copyIDs = function(_) {
 
20507         if (!arguments.length) return copyIDs;
 
20509         copyGraph = history.graph();
 
20516     context.background = function() { return background; };
 
20521     context.features = function() { return features; };
 
20522     context.hasHiddenConnections = function(id) {
 
20523         var graph = history.graph(),
 
20524             entity = graph.entity(id);
 
20525         return features.hasHiddenConnections(entity, graph);
 
20531     context.map = function() { return map; };
 
20532     context.layers = function() { return map.layers; };
 
20533     context.surface = function() { return map.surface; };
 
20534     context.editable = function() { return map.editable(); };
 
20536     context.surfaceRect = function() {
 
20537         // Work around a bug in Firefox.
 
20538         //   http://stackoverflow.com/questions/18153989/
 
20539         //   https://bugzilla.mozilla.org/show_bug.cgi?id=530985
 
20540         return context.surface().node().parentNode.getBoundingClientRect();
 
20552     context.debugFlags = function() {
 
20555     context.setDebug = function(flag, val) {
 
20556         if (arguments.length === 1) val = true;
 
20557         debugFlags[flag] = val;
 
20561     context.getDebug = function(flag) {
 
20562         return flag && debugFlags[flag];
 
20568     context.presets = function(_) {
 
20569         if (!arguments.length) return presets;
 
20571         iD.areaKeys = presets.areaKeys();
 
20577     context.imagery = function(_) {
 
20578         background.load(_);
 
20584     var container, embed;
 
20585     context.container = function(_) {
 
20586         if (!arguments.length) return container;
 
20588         container.classed('id-container', true);
 
20591     context.embed = function(_) {
 
20592         if (!arguments.length) return embed;
 
20600     context.taginfo = function(_) {
 
20601         if (!arguments.length) return taginfo;
 
20608     var assetPath = '';
 
20609     context.assetPath = function(_) {
 
20610         if (!arguments.length) return assetPath;
 
20616     context.assetMap = function(_) {
 
20617         if (!arguments.length) return assetMap;
 
20622     context.asset = function(_) {
 
20623         var filename = assetPath + _;
 
20624         return assetMap[filename] || filename;
 
20627     context.imagePath = function(_) {
 
20628         return context.asset('img/' + _);
 
20631     var locale, localePath;
 
20632     context.locale = function(loc, path) {
 
20636         // Also set iD.detect().locale (unless we detected 'en-us' and openstreetmap wants 'en')..
 
20637         if (!(loc.toLowerCase() === 'en' && iD.detect().locale.toLowerCase() === 'en-us')) {
 
20638             iD.detect().locale = loc;
 
20644     context.loadLocale = function(cb) {
 
20645         if (locale && locale !== 'en' && iD.data.locales.indexOf(locale) !== -1) {
 
20646             localePath = localePath || context.asset('locales/' + locale + '.json');
 
20647             d3.json(localePath, function(err, result) {
 
20648                 window.locale[locale] = result;
 
20649                 window.locale.current(locale);
 
20660     context.projection = iD.geo.RawMercator();
 
20662     locale = iD.detect().locale;
 
20663     if (locale && iD.data.locales.indexOf(locale) === -1) {
 
20664         locale = locale.split('-')[0];
 
20667     history = iD.History(context);
 
20668     context.graph = history.graph;
 
20669     context.changes = history.changes;
 
20670     context.intersects = history.intersects;
 
20672     // Debounce save, since it's a synchronous localStorage write,
 
20673     // and history changes can happen frequently (e.g. when dragging).
 
20674     context.debouncedSave = _.debounce(context.save, 350);
 
20675     function withDebouncedSave(fn) {
 
20676         return function() {
 
20677             var result = fn.apply(history, arguments);
 
20678             context.debouncedSave();
 
20683     context.perform = withDebouncedSave(history.perform);
 
20684     context.replace = withDebouncedSave(history.replace);
 
20685     context.pop = withDebouncedSave(history.pop);
 
20686     context.overwrite = withDebouncedSave(history.overwrite);
 
20687     context.undo = withDebouncedSave(history.undo);
 
20688     context.redo = withDebouncedSave(history.redo);
 
20690     ui = iD.ui(context);
 
20692     connection = iD.Connection();
 
20694     background = iD.Background(context);
 
20696     features = iD.Features(context);
 
20698     map = iD.Map(context);
 
20699     context.mouse = map.mouse;
 
20700     context.extent = map.extent;
 
20701     context.pan = map.pan;
 
20702     context.zoomIn = map.zoomIn;
 
20703     context.zoomOut = map.zoomOut;
 
20704     context.zoomInFurther = map.zoomInFurther;
 
20705     context.zoomOutFurther = map.zoomOutFurther;
 
20706     context.redrawEnable = map.redrawEnable;
 
20708     presets = iD.presets();
 
20710     return d3.rebind(context, dispatch, 'on');
 
20714 iD.version = '1.9.7';
 
20719     var ua = navigator.userAgent,
 
20722     m = ua.match(/(edge)\/?\s*(\.?\d+(\.\d+)*)/i);   // Edge
 
20724         detected.browser = m[1];
 
20725         detected.version = m[2];
 
20727     if (!detected.browser) {
 
20728         m = ua.match(/Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/i);   // IE11
 
20730             detected.browser = 'msie';
 
20731             detected.version = m[1];
 
20734     if (!detected.browser) {
 
20735         m = ua.match(/(opr)\/?\s*(\.?\d+(\.\d+)*)/i);   // Opera 15+
 
20737             detected.browser = 'Opera';
 
20738             detected.version = m[2];
 
20741     if (!detected.browser) {
 
20742         m = ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i);
 
20744             detected.browser = m[1];
 
20745             detected.version = m[2];
 
20746             m = ua.match(/version\/([\.\d]+)/i);
 
20747             if (m !== null) detected.version = m[1];
 
20750     if (!detected.browser) {
 
20751         detected.browser = navigator.appName;
 
20752         detected.version = navigator.appVersion;
 
20755     // keep major.minor version only..
 
20756     detected.version = detected.version.split(/\W/).slice(0,2).join('.');
 
20758     if (detected.browser.toLowerCase() === 'msie') {
 
20759         detected.ie = true;
 
20760         detected.browser = 'Internet Explorer';
 
20761         detected.support = parseFloat(detected.version) >= 11;
 
20763         detected.ie = false;
 
20764         detected.support = true;
 
20767     // Added due to incomplete svg style support. See #715
 
20768     detected.opera = (detected.browser.toLowerCase() === 'opera' && parseFloat(detected.version) < 15 );
 
20770     detected.locale = (navigator.languages && navigator.languages.length)
 
20771         ? navigator.languages[0] : (navigator.language || navigator.userLanguage || 'en-US');
 
20773     detected.filedrop = (window.FileReader && 'ondrop' in window);
 
20776         return navigator.userAgent.indexOf(x) !== -1;
 
20780         detected.os = 'win';
 
20781         detected.platform = 'Windows';
 
20783     else if (nav('Mac')) {
 
20784         detected.os = 'mac';
 
20785         detected.platform = 'Macintosh';
 
20787     else if (nav('X11') || nav('Linux')) {
 
20788         detected.os = 'linux';
 
20789         detected.platform = 'Linux';
 
20792         detected.os = 'win';
 
20793         detected.platform = 'Unknown';
 
20796     iD.detect = function() { return detected; };
 
20799 iD.services.mapillary = function() {
 
20800     var mapillary = {},
 
20801         dispatch = d3.dispatch('loadedImages', 'loadedSigns'),
 
20802         apibase = 'https://a.mapillary.com/v2/',
 
20803         viewercss = 'https://npmcdn.com/mapillary-js@1.3.0/dist/mapillary-js.min.css',
 
20804         viewerjs = 'https://npmcdn.com/mapillary-js@1.3.0/dist/mapillary-js.min.js',
 
20805         clientId = 'NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1ZWYyMmYwNjdmNDdlNmVi',
 
20811     function loadSignStyles(context) {
 
20812         d3.select('head').selectAll('#traffico')
 
20816             .attr('id', 'traffico')
 
20817             .attr('rel', 'stylesheet')
 
20818             .attr('href', context.asset('traffico/stylesheets/traffico.css'));
 
20821     function loadSignDefs(context) {
 
20822         if (iD.services.mapillary.sign_defs) return;
 
20823         iD.services.mapillary.sign_defs = {};
 
20825         _.each(['au', 'br', 'ca', 'de', 'us'], function(region) {
 
20826             d3.json(context.asset('traffico/string-maps/' + region + '-map.json'), function(err, data) {
 
20828                 if (region === 'de') region = 'eu';
 
20829                 iD.services.mapillary.sign_defs[region] = data;
 
20834     function loadViewer() {
 
20836         var wrap = d3.select('#content').selectAll('.mapillary-wrap')
 
20839         var enter = wrap.enter().append('div')
 
20840             .attr('class', 'mapillary-wrap')
 
20841             .classed('al', true)       // 'al'=left,  'ar'=right
 
20842             .classed('hidden', true);
 
20844         enter.append('button')
 
20845             .attr('class', 'thumb-hide')
 
20846             .on('click', function () { mapillary.hideViewer(); })
 
20848             .call(iD.svg.Icon('#icon-close'));
 
20850         enter.append('div')
 
20852             .attr('class', 'mly-wrapper')
 
20853             .classed('active', false);
 
20855         // mapillary-viewercss
 
20856         d3.select('head').selectAll('#mapillary-viewercss')
 
20860             .attr('id', 'mapillary-viewercss')
 
20861             .attr('rel', 'stylesheet')
 
20862             .attr('href', viewercss);
 
20864         // mapillary-viewerjs
 
20865         d3.select('head').selectAll('#mapillary-viewerjs')
 
20869             .attr('id', 'mapillary-viewerjs')
 
20870             .attr('src', viewerjs);
 
20873     function initViewer(imageKey, context) {
 
20875         function nodeChanged(d) {
 
20876             var clicks = iD.services.mapillary.clicks;
 
20877             var index = clicks.indexOf(d.key);
 
20878             if (index > -1) {    // nodechange initiated from clicking on a marker..
 
20879                 clicks.splice(index, 1);
 
20880             } else {             // nodechange initiated from the Mapillary viewer controls..
 
20881                 var loc = d.apiNavImIm ? [d.apiNavImIm.lon, d.apiNavImIm.lat] : [d.latLon.lon, d.latLon.lat];
 
20882                 context.map().centerEase(loc);
 
20883                 mapillary.setSelectedImage(d.key, false);
 
20887         if (Mapillary && imageKey) {
 
20889                 baseImageSize: 320,
 
20898             var viewer = new Mapillary.Viewer('mly', clientId, imageKey, opts);
 
20899             viewer.on('nodechanged', nodeChanged);
 
20900             viewer.on('loadingchanged', mapillary.setViewerLoading);
 
20901             iD.services.mapillary.viewer = viewer;
 
20905     function abortRequest(i) {
 
20909     function nearNullIsland(x, y, z) {
 
20911             var center = Math.pow(2, z - 1),
 
20912                 width = Math.pow(2, z - 6),
 
20913                 min = center - (width / 2),
 
20914                 max = center + (width / 2) - 1;
 
20915             return x >= min && x <= max && y >= min && y <= max;
 
20920     function getTiles(projection, dimensions) {
 
20921         var s = projection.scale() * 2 * Math.PI,
 
20922             z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
 
20923             ts = 256 * Math.pow(2, z - tileZoom),
 
20925                 s / 2 - projection.translate()[0],
 
20926                 s / 2 - projection.translate()[1]];
 
20928         return d3.geo.tile()
 
20929             .scaleExtent([tileZoom, tileZoom])
 
20932             .translate(projection.translate())()
 
20933             .map(function(tile) {
 
20934                 var x = tile[0] * ts - origin[0],
 
20935                     y = tile[1] * ts - origin[1];
 
20938                     id: tile.toString(),
 
20939                     extent: iD.geo.Extent(
 
20940                         projection.invert([x, y + ts]),
 
20941                         projection.invert([x + ts, y]))
 
20947     function loadTiles(which, url, projection, dimensions) {
 
20948         var tiles = getTiles(projection, dimensions).filter(function(t) {
 
20949               var xyz = t.id.split(',');
 
20950               return !nearNullIsland(xyz[0], xyz[1], xyz[2]);
 
20953         _.filter(which.inflight, function(v, k) {
 
20954             var wanted = _.find(tiles, function(tile) { return k === (tile.id + ',0'); });
 
20955             if (!wanted) delete which.inflight[k];
 
20957         }).map(abortRequest);
 
20959         tiles.forEach(function(tile) {
 
20960             loadTilePage(which, url, tile, 0);
 
20964     function loadTilePage(which, url, tile, page) {
 
20965         var cache = iD.services.mapillary.cache[which],
 
20966             id = tile.id + ',' + String(page),
 
20967             rect = tile.extent.rectangle();
 
20969         if (cache.loaded[id] || cache.inflight[id]) return;
 
20971         cache.inflight[id] = d3.json(url +
 
20976                 client_id: clientId,
 
20981             }), function(err, data) {
 
20982                 cache.loaded[id] = true;
 
20983                 delete cache.inflight[id];
 
20984                 if (err || !data.features || !data.features.length) return;
 
20987                     nextPage = page + 1,
 
20990                 for (var i = 0; i < data.features.length; i++) {
 
20991                     feature = data.features[i];
 
20992                     loc = feature.geometry.coordinates;
 
20993                     d = { key: feature.properties.key, loc: loc };
 
20994                     if (which === 'images') d.ca = feature.properties.ca;
 
20995                     if (which === 'signs') d.signs = feature.properties.rects;
 
20997                     features.push([loc[0], loc[1], loc[0], loc[1], d]);
 
21000                 cache.rtree.load(features);
 
21002                 if (which === 'images') dispatch.loadedImages();
 
21003                 if (which === 'signs') dispatch.loadedSigns();
 
21005                 if (data.features.length === maxResults && nextPage < maxPages) {
 
21006                     loadTilePage(which, url, tile, nextPage);
 
21012     mapillary.loadImages = function(projection, dimensions) {
 
21013         var url = apibase + 'search/im/geojson?';
 
21014         loadTiles('images', url, projection, dimensions);
 
21017     mapillary.loadSigns = function(context, projection, dimensions) {
 
21018         var url = apibase + 'search/im/geojson/or?';
 
21019         loadSignStyles(context);
 
21020         loadSignDefs(context);
 
21021         loadTiles('signs', url, projection, dimensions);
 
21024     mapillary.loadViewer = function() {
 
21029     // partition viewport into `psize` x `psize` regions
 
21030     function partitionViewport(psize, projection, dimensions) {
 
21031         psize = psize || 16;
 
21032         var cols = d3.range(0, dimensions[0], psize),
 
21033             rows = d3.range(0, dimensions[1], psize),
 
21036         rows.forEach(function(y) {
 
21037             cols.forEach(function(x) {
 
21038                 var min = [x, y + psize],
 
21039                     max = [x + psize, y];
 
21041                     iD.geo.Extent(projection.invert(min), projection.invert(max)));
 
21048     // no more than `limit` results per partition.
 
21049     function searchLimited(psize, limit, projection, dimensions, rtree) {
 
21050         limit = limit || 3;
 
21052         var partitions = partitionViewport(psize, projection, dimensions);
 
21053         return _.flatten(_.compact(_.map(partitions, function(extent) {
 
21054             return rtree.search(extent.rectangle())
 
21056                 .map(function(d) { return d[4]; });
 
21060     mapillary.images = function(projection, dimensions) {
 
21061         var psize = 16, limit = 3;
 
21062         return searchLimited(psize, limit, projection, dimensions, iD.services.mapillary.cache.images.rtree);
 
21065     mapillary.signs = function(projection, dimensions) {
 
21066         var psize = 32, limit = 3;
 
21067         return searchLimited(psize, limit, projection, dimensions, iD.services.mapillary.cache.signs.rtree);
 
21070     mapillary.signsSupported = function() {
 
21071         var detected = iD.detect();
 
21072         return (!(detected.ie || detected.browser.toLowerCase() === 'safari'));
 
21075     mapillary.signHTML = function(d) {
 
21076         if (!iD.services.mapillary.sign_defs) return;
 
21078         var detectionPackage = d.signs[0].package,
 
21079             type = d.signs[0].type,
 
21080             country = detectionPackage.split('_')[1];
 
21082         return iD.services.mapillary.sign_defs[country][type];
 
21085     mapillary.showViewer = function() {
 
21086         d3.select('#content')
 
21087             .selectAll('.mapillary-wrap')
 
21088             .classed('hidden', false)
 
21089             .selectAll('.mly-wrapper')
 
21090             .classed('active', true);
 
21095     mapillary.hideViewer = function() {
 
21096         d3.select('#content')
 
21097             .selectAll('.mapillary-wrap')
 
21098             .classed('hidden', true)
 
21099             .selectAll('.mly-wrapper')
 
21100             .classed('active', false);
 
21102         d3.selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
 
21103             .classed('selected', false);
 
21105         iD.services.mapillary.image = null;
 
21110     mapillary.setViewerLoading = function(loading) {
 
21111         var canvas = d3.select('#content')
 
21112             .selectAll('.mly-wrapper canvas');
 
21114         if (canvas.empty()) return;   // viewer not loaded yet
 
21116         var cover = d3.select('#content')
 
21117             .selectAll('.mly-wrapper .Cover');
 
21119         cover.classed('CoverDone', !loading);
 
21121         var button = cover.selectAll('.CoverButton')
 
21122             .data(loading ? [0] : []);
 
21126             .attr('class', 'CoverButton')
 
21128             .attr('class', 'uil-ripple-css')
 
21137     mapillary.updateViewer = function(imageKey, context) {
 
21138         if (!iD.services.mapillary) return;
 
21139         if (!imageKey) return;
 
21141         if (!iD.services.mapillary.viewer) {
 
21142             initViewer(imageKey, context);
 
21144             iD.services.mapillary.viewer.moveToKey(imageKey);
 
21150     mapillary.getSelectedImage = function() {
 
21151         if (!iD.services.mapillary) return null;
 
21152         return iD.services.mapillary.image;
 
21155     mapillary.setSelectedImage = function(imageKey, fromClick) {
 
21156         if (!iD.services.mapillary) return null;
 
21158         iD.services.mapillary.image = imageKey;
 
21160             iD.services.mapillary.clicks.push(imageKey);
 
21163         d3.selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
 
21164             .classed('selected', function(d) { return d.key === imageKey; });
 
21169     mapillary.reset = function() {
 
21170         var cache = iD.services.mapillary.cache;
 
21173             _.forEach(cache.images.inflight, abortRequest);
 
21174             _.forEach(cache.signs.inflight, abortRequest);
 
21177         iD.services.mapillary.cache = {
 
21178             images: { inflight: {}, loaded: {}, rtree: rbush() },
 
21179             signs:  { inflight: {}, loaded: {}, rtree: rbush() }
 
21182         iD.services.mapillary.image = null;
 
21183         iD.services.mapillary.clicks = [];
 
21189     if (!iD.services.mapillary.cache) {
 
21193     return d3.rebind(mapillary, dispatch, 'on');
 
21195 iD.services.nominatim  = function() {
 
21196     var nominatim = {},
 
21197         endpoint = 'https://nominatim.openstreetmap.org/reverse?';
 
21200     nominatim.countryCode = function(location, callback) {
 
21201         var cache = iD.services.nominatim.cache,
 
21202             countryCodes = cache.search([location[0], location[1], location[0], location[1]]);
 
21204         if (countryCodes.length > 0)
 
21205             return callback(null, countryCodes[0][4]);
 
21213             }), function(err, result) {
 
21215                     return callback(err);
 
21216                 else if (result && result.error)
 
21217                     return callback(result.error);
 
21219                 var extent = iD.geo.Extent(location).padByMeters(1000);
 
21221                 cache.insert(extent.rectangle().concat(result.address.country_code));
 
21223                 callback(null, result.address.country_code);
 
21227     nominatim.reset = function() {
 
21228         iD.services.nominatim.cache = rbush();
 
21233     if (!iD.services.nominatim.cache) {
 
21239 iD.services.taginfo = function() {
 
21241         endpoint = 'https://taginfo.openstreetmap.org/api/4/',
 
21243             point: 'count_nodes',
 
21244             vertex: 'count_nodes',
 
21245             area: 'count_ways',
 
21256     function sets(parameters, n, o) {
 
21257         if (parameters.geometry && o[parameters.geometry]) {
 
21258             parameters[n] = o[parameters.geometry];
 
21263     function setFilter(parameters) {
 
21264         return sets(parameters, 'filter', tag_filters);
 
21267     function setSort(parameters) {
 
21268         return sets(parameters, 'sortname', tag_sorts);
 
21271     function clean(parameters) {
 
21272         return _.omit(parameters, 'geometry', 'debounce');
 
21275     function filterKeys(type) {
 
21276         var count_type = type ? 'count_' + type : 'count_all';
 
21277         return function(d) {
 
21278             return parseFloat(d[count_type]) > 2500 || d.in_wiki;
 
21282     function filterMultikeys() {
 
21283         return function(d) {
 
21284             return (d.key.match(/:/g) || []).length === 1;  // exactly one ':'
 
21288     function filterValues() {
 
21289         return function(d) {
 
21290             if (d.value.match(/[A-Z*;,]/) !== null) return false;  // exclude some punctuation, uppercase letters
 
21291             return parseFloat(d.fraction) > 0.0 || d.in_wiki;
 
21295     function valKey(d) {
 
21302     function valKeyDescription(d) {
 
21305             title: d.description || d.value
 
21309     // sort keys with ':' lower than keys without ':'
 
21310     function sortKeys(a, b) {
 
21311         return (a.key.indexOf(':') === -1 && b.key.indexOf(':') !== -1) ? -1
 
21312             : (a.key.indexOf(':') !== -1 && b.key.indexOf(':') === -1) ? 1
 
21316     var debounced = _.debounce(d3.json, 100, true);
 
21318     function request(url, debounce, callback) {
 
21319         var cache = iD.services.taginfo.cache;
 
21322             callback(null, cache[url]);
 
21323         } else if (debounce) {
 
21324             debounced(url, done);
 
21326             d3.json(url, done);
 
21329         function done(err, data) {
 
21330             if (!err) cache[url] = data;
 
21331             callback(err, data);
 
21335     taginfo.keys = function(parameters, callback) {
 
21336         var debounce = parameters.debounce;
 
21337         parameters = clean(setSort(parameters));
 
21338         request(endpoint + 'keys/all?' +
 
21339             iD.util.qsString(_.extend({
 
21341                 sortname: 'count_all',
 
21344             }, parameters)), debounce, function(err, d) {
 
21345                 if (err) return callback(err);
 
21346                 var f = filterKeys(parameters.filter);
 
21347                 callback(null, d.data.filter(f).sort(sortKeys).map(valKey));
 
21351     taginfo.multikeys = function(parameters, callback) {
 
21352         var debounce = parameters.debounce;
 
21353         parameters = clean(setSort(parameters));
 
21354         request(endpoint + 'keys/all?' +
 
21355             iD.util.qsString(_.extend({
 
21357                 sortname: 'count_all',
 
21360             }, parameters)), debounce, function(err, d) {
 
21361                 if (err) return callback(err);
 
21362                 var f = filterMultikeys();
 
21363                 callback(null, d.data.filter(f).map(valKey));
 
21367     taginfo.values = function(parameters, callback) {
 
21368         var debounce = parameters.debounce;
 
21369         parameters = clean(setSort(setFilter(parameters)));
 
21370         request(endpoint + 'key/values?' +
 
21371             iD.util.qsString(_.extend({
 
21373                 sortname: 'count_all',
 
21376             }, parameters)), debounce, function(err, d) {
 
21377                 if (err) return callback(err);
 
21378                 var f = filterValues();
 
21379                 callback(null, d.data.filter(f).map(valKeyDescription));
 
21383     taginfo.docs = function(parameters, callback) {
 
21384         var debounce = parameters.debounce;
 
21385         parameters = clean(setSort(parameters));
 
21387         var path = 'key/wiki_pages?';
 
21388         if (parameters.value) path = 'tag/wiki_pages?';
 
21389         else if (parameters.rtype) path = 'relation/wiki_pages?';
 
21391         request(endpoint + path + iD.util.qsString(parameters), debounce, function(err, d) {
 
21392             if (err) return callback(err);
 
21393             callback(null, d.data);
 
21397     taginfo.endpoint = function(_) {
 
21398         if (!arguments.length) return endpoint;
 
21403     taginfo.reset = function() {
 
21404         iD.services.taginfo.cache = {};
 
21409     if (!iD.services.taginfo.cache) {
 
21415 iD.services.wikidata = function() {
 
21417         endpoint = 'https://www.wikidata.org/w/api.php?';
 
21419     // Given a Wikipedia language and article title, return an array of
 
21420     // corresponding Wikidata entities.
 
21421     wiki.itemsByTitle = function(lang, title, callback) {
 
21422         lang = lang || 'en';
 
21423         d3.jsonp(endpoint + iD.util.qsString({
 
21424             action: 'wbgetentities',
 
21426             sites: lang.replace(/-/g, '_') + 'wiki',
 
21428             languages: 'en', // shrink response by filtering to one language
 
21429             callback: '{callback}'
 
21430         }), function(data) {
 
21431             callback(title, data.entities || {});
 
21437 iD.services.wikipedia = function() {
 
21439         endpoint = 'https://en.wikipedia.org/w/api.php?';
 
21441     wiki.search = function(lang, query, callback) {
 
21442         lang = lang || 'en';
 
21443         d3.jsonp(endpoint.replace('en', lang) +
 
21448                 srinfo: 'suggestion',
 
21450                 callback: '{callback}',
 
21452             }), function(data) {
 
21453                 if (!data.query) return;
 
21454                 callback(query, data.query.search.map(function(d) {
 
21460     wiki.suggestions = function(lang, query, callback) {
 
21461         lang = lang || 'en';
 
21462         d3.jsonp(endpoint.replace('en', lang) +
 
21464                 action: 'opensearch',
 
21468                 callback: '{callback}',
 
21471                 callback(d[0], d[1]);
 
21475     wiki.translations = function(lang, title, callback) {
 
21476         d3.jsonp(endpoint.replace('en', lang) +
 
21481                 callback: '{callback}',
 
21485                 var list = d.query.pages[Object.keys(d.query.pages)[0]],
 
21487                 if (list && list.langlinks) {
 
21488                     list.langlinks.forEach(function(d) {
 
21489                         translations[d.lang] = d['*'];
 
21491                     callback(translations);
 
21500 iD.util.tagText = function(entity) {
 
21501     return d3.entries(entity.tags).map(function(e) {
 
21502         return e.key + '=' + e.value;
 
21506 iD.util.entitySelector = function(ids) {
 
21507     return ids.length ? '.' + ids.join(',.') : 'nothing';
 
21510 iD.util.entityOrMemberSelector = function(ids, graph) {
 
21511     var s = iD.util.entitySelector(ids);
 
21513     ids.forEach(function(id) {
 
21514         var entity = graph.hasEntity(id);
 
21515         if (entity && entity.type === 'relation') {
 
21516             entity.members.forEach(function(member) {
 
21517                 s += ',.' + member.id;
 
21525 iD.util.displayName = function(entity) {
 
21526     var localeName = 'name:' + iD.detect().locale.toLowerCase().split('-')[0];
 
21527     return entity.tags[localeName] || entity.tags.name || entity.tags.ref;
 
21530 iD.util.displayType = function(id) {
 
21532         n: t('inspector.node'),
 
21533         w: t('inspector.way'),
 
21534         r: t('inspector.relation')
 
21538 iD.util.stringQs = function(str) {
 
21539     return str.split('&').reduce(function(obj, pair){
 
21540         var parts = pair.split('=');
 
21541         if (parts.length === 2) {
 
21542             obj[parts[0]] = (null === parts[1]) ? '' : decodeURIComponent(parts[1]);
 
21548 iD.util.qsString = function(obj, noencode) {
 
21549     function softEncode(s) {
 
21550       // encode everything except special characters used in certain hash parameters:
 
21551       // "/" in map states, ":", ",", {" and "}" in background
 
21552       return encodeURIComponent(s).replace(/(%2F|%3A|%2C|%7B|%7D)/g, decodeURIComponent);
 
21554     return Object.keys(obj).sort().map(function(key) {
 
21555         return encodeURIComponent(key) + '=' + (
 
21556             noencode ? softEncode(obj[key]) : encodeURIComponent(obj[key]));
 
21560 iD.util.prefixDOMProperty = function(property) {
 
21561     var prefixes = ['webkit', 'ms', 'moz', 'o'],
 
21563         n = prefixes.length,
 
21569     property = property.substr(0, 1).toUpperCase() + property.substr(1);
 
21572         if (prefixes[i] + property in s)
 
21573             return prefixes[i] + property;
 
21578 iD.util.prefixCSSProperty = function(property) {
 
21579     var prefixes = ['webkit', 'ms', 'Moz', 'O'],
 
21581         n = prefixes.length,
 
21582         s = document.body.style;
 
21584     if (property.toLowerCase() in s)
 
21585         return property.toLowerCase();
 
21588         if (prefixes[i] + property in s)
 
21589             return '-' + prefixes[i].toLowerCase() + property.replace(/([A-Z])/g, '-$1').toLowerCase();
 
21595 iD.util.setTransform = function(el, x, y, scale) {
 
21596     var prop = iD.util.transformProperty = iD.util.transformProperty || iD.util.prefixCSSProperty('Transform'),
 
21597         translate = iD.detect().opera ?
 
21598             'translate('   + x + 'px,' + y + 'px)' :
 
21599             'translate3d(' + x + 'px,' + y + 'px,0)';
 
21600     return el.style(prop, translate + (scale ? ' scale(' + scale + ')' : ''));
 
21603 iD.util.getStyle = function(selector) {
 
21604     for (var i = 0; i < document.styleSheets.length; i++) {
 
21605         var rules = document.styleSheets[i].rules || document.styleSheets[i].cssRules || [];
 
21606         for (var k = 0; k < rules.length; k++) {
 
21607             var selectorText = rules[k].selectorText && rules[k].selectorText.split(', ');
 
21608             if (_.includes(selectorText, selector)) {
 
21615 iD.util.editDistance = function(a, b) {
 
21616     if (a.length === 0) return b.length;
 
21617     if (b.length === 0) return a.length;
 
21619     for (var i = 0; i <= b.length; i++) { matrix[i] = [i]; }
 
21620     for (var j = 0; j <= a.length; j++) { matrix[0][j] = j; }
 
21621     for (i = 1; i <= b.length; i++) {
 
21622         for (j = 1; j <= a.length; j++) {
 
21623             if (b.charAt(i-1) === a.charAt(j-1)) {
 
21624                 matrix[i][j] = matrix[i-1][j-1];
 
21626                 matrix[i][j] = Math.min(matrix[i-1][j-1] + 1, // substitution
 
21627                     Math.min(matrix[i][j-1] + 1, // insertion
 
21628                     matrix[i-1][j] + 1)); // deletion
 
21632     return matrix[b.length][a.length];
 
21635 // a d3.mouse-alike which
 
21636 // 1. Only works on HTML elements, not SVG
 
21637 // 2. Does not cause style recalculation
 
21638 iD.util.fastMouse = function(container) {
 
21639     var rect = container.getBoundingClientRect(),
 
21640         rectLeft = rect.left,
 
21641         rectTop = rect.top,
 
21642         clientLeft = +container.clientLeft,
 
21643         clientTop = +container.clientTop;
 
21644     return function(e) {
 
21646             e.clientX - rectLeft - clientLeft,
 
21647             e.clientY - rectTop - clientTop];
 
21651 /* eslint-disable no-proto */
 
21652 iD.util.getPrototypeOf = Object.getPrototypeOf || function(obj) { return obj.__proto__; };
 
21653 /* eslint-enable no-proto */
 
21655 iD.util.asyncMap = function(inputs, func, callback) {
 
21656     var remaining = inputs.length,
 
21660     inputs.forEach(function(d, i) {
 
21661         func(d, function done(err, data) {
 
21665             if (!remaining) callback(errors, results);
 
21670 // wraps an index to an interval [0..length-1]
 
21671 iD.util.wrap = function(index, length) {
 
21673         index += Math.ceil(-index/length)*length;
 
21674     return index % length;
 
21676 // A per-domain session mutex backed by a cookie and dead man's
 
21677 // switch. If the session crashes, the mutex will auto-release
 
21678 // after 5 seconds.
 
21680 iD.util.SessionMutex = function(name) {
 
21685         var expires = new Date();
 
21686         expires.setSeconds(expires.getSeconds() + 5);
 
21687         document.cookie = name + '=1; expires=' + expires.toUTCString();
 
21690     mutex.lock = function() {
 
21691         if (intervalID) return true;
 
21692         var cookie = document.cookie.replace(new RegExp('(?:(?:^|.*;)\\s*' + name + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1');
 
21693         if (cookie) return false;
 
21695         intervalID = window.setInterval(renew, 4000);
 
21699     mutex.unlock = function() {
 
21700         if (!intervalID) return;
 
21701         document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT';
 
21702         clearInterval(intervalID);
 
21706     mutex.locked = function() {
 
21707         return !!intervalID;
 
21712 iD.util.SuggestNames = function(preset, suggestions) {
 
21713     preset = preset.id.split('/', 2);
 
21717     return function(value, callback) {
 
21719         if (value && value.length > 2) {
 
21720             if (suggestions[k] && suggestions[k][v]) {
 
21721                 for (var sugg in suggestions[k][v]) {
 
21722                     var dist = iD.util.editDistance(value, sugg.substring(0, value.length));
 
21732             result.sort(function(a, b) {
 
21733                 return a.dist - b.dist;
 
21736         result = result.slice(0,3);
 
21742 iD.geo.roundCoords = function(c) {
 
21743     return [Math.floor(c[0]), Math.floor(c[1])];
 
21746 iD.geo.interp = function(p1, p2, t) {
 
21747     return [p1[0] + (p2[0] - p1[0]) * t,
 
21748             p1[1] + (p2[1] - p1[1]) * t];
 
21751 // 2D cross product of OA and OB vectors, i.e. z-component of their 3D cross product.
 
21752 // Returns a positive value, if OAB makes a counter-clockwise turn,
 
21753 // negative for clockwise turn, and zero if the points are collinear.
 
21754 iD.geo.cross = function(o, a, b) {
 
21755     return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]);
 
21758 // http://jsperf.com/id-dist-optimization
 
21759 iD.geo.euclideanDistance = function(a, b) {
 
21760     var x = a[0] - b[0], y = a[1] - b[1];
 
21761     return Math.sqrt((x * x) + (y * y));
 
21764 // using WGS84 polar radius (6356752.314245179 m)
 
21765 // const = 2 * PI * r / 360
 
21766 iD.geo.latToMeters = function(dLat) {
 
21767     return dLat * 110946.257617;
 
21770 // using WGS84 equatorial radius (6378137.0 m)
 
21771 // const = 2 * PI * r / 360
 
21772 iD.geo.lonToMeters = function(dLon, atLat) {
 
21773     return Math.abs(atLat) >= 90 ? 0 :
 
21774         dLon * 111319.490793 * Math.abs(Math.cos(atLat * (Math.PI/180)));
 
21777 // using WGS84 polar radius (6356752.314245179 m)
 
21778 // const = 2 * PI * r / 360
 
21779 iD.geo.metersToLat = function(m) {
 
21780     return m / 110946.257617;
 
21783 // using WGS84 equatorial radius (6378137.0 m)
 
21784 // const = 2 * PI * r / 360
 
21785 iD.geo.metersToLon = function(m, atLat) {
 
21786     return Math.abs(atLat) >= 90 ? 0 :
 
21787         m / 111319.490793 / Math.abs(Math.cos(atLat * (Math.PI/180)));
 
21790 iD.geo.offsetToMeters = function(offset) {
 
21791     var equatRadius = 6356752.314245179,
 
21792         polarRadius = 6378137.0,
 
21796         offset[0] * 2 * Math.PI * equatRadius / tileSize,
 
21797         -offset[1] * 2 * Math.PI * polarRadius / tileSize
 
21801 iD.geo.metersToOffset = function(meters) {
 
21802     var equatRadius = 6356752.314245179,
 
21803         polarRadius = 6378137.0,
 
21807         meters[0] * tileSize / (2 * Math.PI * equatRadius),
 
21808         -meters[1] * tileSize / (2 * Math.PI * polarRadius)
 
21812 // Equirectangular approximation of spherical distances on Earth
 
21813 iD.geo.sphericalDistance = function(a, b) {
 
21814     var x = iD.geo.lonToMeters(a[0] - b[0], (a[1] + b[1]) / 2),
 
21815         y = iD.geo.latToMeters(a[1] - b[1]);
 
21816     return Math.sqrt((x * x) + (y * y));
 
21819 iD.geo.edgeEqual = function(a, b) {
 
21820     return (a[0] === b[0] && a[1] === b[1]) ||
 
21821         (a[0] === b[1] && a[1] === b[0]);
 
21824 // Return the counterclockwise angle in the range (-pi, pi)
 
21825 // between the positive X axis and the line intersecting a and b.
 
21826 iD.geo.angle = function(a, b, projection) {
 
21827     a = projection(a.loc);
 
21828     b = projection(b.loc);
 
21829     return Math.atan2(b[1] - a[1], b[0] - a[0]);
 
21832 // Choose the edge with the minimal distance from `point` to its orthogonal
 
21833 // projection onto that edge, if such a projection exists, or the distance to
 
21834 // the closest vertex on that edge. Returns an object with the `index` of the
 
21835 // chosen edge, the chosen `loc` on that edge, and the `distance` to to it.
 
21836 iD.geo.chooseEdge = function(nodes, point, projection) {
 
21837     var dist = iD.geo.euclideanDistance,
 
21838         points = nodes.map(function(n) { return projection(n.loc); }),
 
21842     function dot(p, q) {
 
21843         return p[0] * q[0] + p[1] * q[1];
 
21846     for (var i = 0; i < points.length - 1; i++) {
 
21848             s = [points[i + 1][0] - o[0],
 
21849                  points[i + 1][1] - o[1]],
 
21850             v = [point[0] - o[0],
 
21852             proj = dot(v, s) / dot(s, s),
 
21857         } else if (proj > 1) {
 
21860             p = [o[0] + proj * s[0], o[1] + proj * s[1]];
 
21863         var d = dist(p, point);
 
21867             loc = projection.invert(p);
 
21878 // Return the intersection point of 2 line segments.
 
21879 // From https://github.com/pgkelley4/line-segments-intersect
 
21880 // This uses the vector cross product approach described below:
 
21881 //  http://stackoverflow.com/a/565282/786339
 
21882 iD.geo.lineIntersection = function(a, b) {
 
21883     function subtractPoints(point1, point2) {
 
21884         return [point1[0] - point2[0], point1[1] - point2[1]];
 
21886     function crossProduct(point1, point2) {
 
21887         return point1[0] * point2[1] - point1[1] * point2[0];
 
21890     var p = [a[0][0], a[0][1]],
 
21891         p2 = [a[1][0], a[1][1]],
 
21892         q = [b[0][0], b[0][1]],
 
21893         q2 = [b[1][0], b[1][1]],
 
21894         r = subtractPoints(p2, p),
 
21895         s = subtractPoints(q2, q),
 
21896         uNumerator = crossProduct(subtractPoints(q, p), r),
 
21897         denominator = crossProduct(r, s);
 
21899     if (uNumerator && denominator) {
 
21900         var u = uNumerator / denominator,
 
21901             t = crossProduct(subtractPoints(q, p), s) / denominator;
 
21903         if ((t >= 0) && (t <= 1) && (u >= 0) && (u <= 1)) {
 
21904             return iD.geo.interp(p, p2, t);
 
21911 iD.geo.pathIntersections = function(path1, path2) {
 
21912     var intersections = [];
 
21913     for (var i = 0; i < path1.length - 1; i++) {
 
21914         for (var j = 0; j < path2.length - 1; j++) {
 
21915             var a = [ path1[i], path1[i+1] ],
 
21916                 b = [ path2[j], path2[j+1] ],
 
21917                 hit = iD.geo.lineIntersection(a, b);
 
21918             if (hit) intersections.push(hit);
 
21921     return intersections;
 
21924 // Return whether point is contained in polygon.
 
21926 // `point` should be a 2-item array of coordinates.
 
21927 // `polygon` should be an array of 2-item arrays of coordinates.
 
21929 // From https://github.com/substack/point-in-polygon.
 
21930 // ray-casting algorithm based on
 
21931 // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
 
21933 iD.geo.pointInPolygon = function(point, polygon) {
 
21938     for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
 
21939         var xi = polygon[i][0], yi = polygon[i][1];
 
21940         var xj = polygon[j][0], yj = polygon[j][1];
 
21942         var intersect = ((yi > y) !== (yj > y)) &&
 
21943             (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
 
21944         if (intersect) inside = !inside;
 
21950 iD.geo.polygonContainsPolygon = function(outer, inner) {
 
21951     return _.every(inner, function(point) {
 
21952         return iD.geo.pointInPolygon(point, outer);
 
21956 iD.geo.polygonIntersectsPolygon = function(outer, inner, checkSegments) {
 
21957     function testSegments(outer, inner) {
 
21958         for (var i = 0; i < outer.length - 1; i++) {
 
21959             for (var j = 0; j < inner.length - 1; j++) {
 
21960                 var a = [ outer[i], outer[i+1] ],
 
21961                     b = [ inner[j], inner[j+1] ];
 
21962                 if (iD.geo.lineIntersection(a, b)) return true;
 
21968     function testPoints(outer, inner) {
 
21969         return _.some(inner, function(point) {
 
21970             return iD.geo.pointInPolygon(point, outer);
 
21974    return testPoints(outer, inner) || (!!checkSegments && testSegments(outer, inner));
 
21977 iD.geo.pathLength = function(path) {
 
21980     for (var i = 0; i < path.length - 1; i++) {
 
21981         dx = path[i][0] - path[i + 1][0];
 
21982         dy = path[i][1] - path[i + 1][1];
 
21983         length += Math.sqrt(dx * dx + dy * dy);
 
21987 iD.geo.Extent = function geoExtent(min, max) {
 
21988     if (!(this instanceof iD.geo.Extent)) return new iD.geo.Extent(min, max);
 
21989     if (min instanceof iD.geo.Extent) {
 
21991     } else if (min && min.length === 2 && min[0].length === 2 && min[1].length === 2) {
 
21995         this[0] = min        || [ Infinity,  Infinity];
 
21996         this[1] = max || min || [-Infinity, -Infinity];
 
22000 iD.geo.Extent.prototype = new Array(2);
 
22002 _.extend(iD.geo.Extent.prototype, {
 
22003     equals: function (obj) {
 
22004         return this[0][0] === obj[0][0] &&
 
22005             this[0][1] === obj[0][1] &&
 
22006             this[1][0] === obj[1][0] &&
 
22007             this[1][1] === obj[1][1];
 
22010     extend: function(obj) {
 
22011         if (!(obj instanceof iD.geo.Extent)) obj = new iD.geo.Extent(obj);
 
22012         return iD.geo.Extent([Math.min(obj[0][0], this[0][0]),
 
22013                               Math.min(obj[0][1], this[0][1])],
 
22014                              [Math.max(obj[1][0], this[1][0]),
 
22015                               Math.max(obj[1][1], this[1][1])]);
 
22018     _extend: function(extent) {
 
22019         this[0][0] = Math.min(extent[0][0], this[0][0]);
 
22020         this[0][1] = Math.min(extent[0][1], this[0][1]);
 
22021         this[1][0] = Math.max(extent[1][0], this[1][0]);
 
22022         this[1][1] = Math.max(extent[1][1], this[1][1]);
 
22026         return Math.abs((this[1][0] - this[0][0]) * (this[1][1] - this[0][1]));
 
22029     center: function() {
 
22030         return [(this[0][0] + this[1][0]) / 2,
 
22031                 (this[0][1] + this[1][1]) / 2];
 
22034     rectangle: function() {
 
22035         return [this[0][0], this[0][1], this[1][0], this[1][1]];
 
22038     polygon: function() {
 
22040             [this[0][0], this[0][1]],
 
22041             [this[0][0], this[1][1]],
 
22042             [this[1][0], this[1][1]],
 
22043             [this[1][0], this[0][1]],
 
22044             [this[0][0], this[0][1]]
 
22048     contains: function(obj) {
 
22049         if (!(obj instanceof iD.geo.Extent)) obj = new iD.geo.Extent(obj);
 
22050         return obj[0][0] >= this[0][0] &&
 
22051                obj[0][1] >= this[0][1] &&
 
22052                obj[1][0] <= this[1][0] &&
 
22053                obj[1][1] <= this[1][1];
 
22056     intersects: function(obj) {
 
22057         if (!(obj instanceof iD.geo.Extent)) obj = new iD.geo.Extent(obj);
 
22058         return obj[0][0] <= this[1][0] &&
 
22059                obj[0][1] <= this[1][1] &&
 
22060                obj[1][0] >= this[0][0] &&
 
22061                obj[1][1] >= this[0][1];
 
22064     intersection: function(obj) {
 
22065         if (!this.intersects(obj)) return new iD.geo.Extent();
 
22066         return new iD.geo.Extent([Math.max(obj[0][0], this[0][0]),
 
22067                                   Math.max(obj[0][1], this[0][1])],
 
22068                                  [Math.min(obj[1][0], this[1][0]),
 
22069                                   Math.min(obj[1][1], this[1][1])]);
 
22072     percentContainedIn: function(obj) {
 
22073         if (!(obj instanceof iD.geo.Extent)) obj = new iD.geo.Extent(obj);
 
22074         var a1 = this.intersection(obj).area(),
 
22077         if (a1 === Infinity || a2 === Infinity || a1 === 0 || a2 === 0) {
 
22084     padByMeters: function(meters) {
 
22085         var dLat = iD.geo.metersToLat(meters),
 
22086             dLon = iD.geo.metersToLon(meters, this.center()[1]);
 
22087         return iD.geo.Extent(
 
22088                 [this[0][0] - dLon, this[0][1] - dLat],
 
22089                 [this[1][0] + dLon, this[1][1] + dLat]);
 
22092     toParam: function() {
 
22093         return this.rectangle().join(',');
 
22097 iD.geo.Turn = function(turn) {
 
22098     if (!(this instanceof iD.geo.Turn))
 
22099         return new iD.geo.Turn(turn);
 
22100     _.extend(this, turn);
 
22103 iD.geo.Intersection = function(graph, vertexId) {
 
22104     var vertex = graph.entity(vertexId),
 
22105         parentWays = graph.parentWays(vertex),
 
22109     function addHighway(way, adjacentNodeId) {
 
22110         if (highways[adjacentNodeId]) {
 
22111             coincident.push(adjacentNodeId);
 
22113             highways[adjacentNodeId] = way;
 
22117     // Pre-split ways that would need to be split in
 
22118     // order to add a restriction. The real split will
 
22119     // happen when the restriction is added.
 
22120     parentWays.forEach(function(way) {
 
22121         if (!way.tags.highway || way.isArea() || way.isDegenerate())
 
22124         var isFirst = (vertexId === way.first()),
 
22125             isLast = (vertexId === way.last()),
 
22126             isAffix = (isFirst || isLast),
 
22127             isClosingNode = (isFirst && isLast);
 
22129         if (isAffix && !isClosingNode) {
 
22130             var index = (isFirst ? 1 : way.nodes.length - 2);
 
22131             addHighway(way, way.nodes[index]);
 
22134             var splitIndex, wayA, wayB, indexA, indexB;
 
22135             if (isClosingNode) {
 
22136                 splitIndex = Math.ceil(way.nodes.length / 2);  // split at midpoint
 
22137                 wayA = iD.Way({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex)});
 
22138                 wayB = iD.Way({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
 
22140                 indexB = way.nodes.length - 2;
 
22142                 splitIndex = _.indexOf(way.nodes, vertex.id, 1);  // split at vertexid
 
22143                 wayA = iD.Way({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex + 1)});
 
22144                 wayB = iD.Way({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
 
22145                 indexA = splitIndex - 1;
 
22146                 indexB = splitIndex + 1;
 
22148             graph = graph.replace(wayA).replace(wayB);
 
22149             addHighway(wayA, way.nodes[indexA]);
 
22150             addHighway(wayB, way.nodes[indexB]);
 
22154     // remove any ways from this intersection that are coincident
 
22155     // (i.e. any adjacent node used by more than one intersecting way)
 
22156     coincident.forEach(function (n) {
 
22157         delete highways[n];
 
22161     var intersection = {
 
22162         highways: highways,
 
22163         ways: _.values(highways),
 
22167     intersection.adjacentNodeId = function(fromWayId) {
 
22168         return _.find(_.keys(highways), function(k) {
 
22169             return highways[k].id === fromWayId;
 
22173     intersection.turns = function(fromNodeId) {
 
22174         var start = highways[fromNodeId];
 
22178         if (start.first() === vertex.id && start.tags.oneway === 'yes')
 
22180         if (start.last() === vertex.id && start.tags.oneway === '-1')
 
22183         function withRestriction(turn) {
 
22184             graph.parentRelations(graph.entity(turn.from.way)).forEach(function(relation) {
 
22185                 if (relation.tags.type !== 'restriction')
 
22188                 var f = relation.memberByRole('from'),
 
22189                     t = relation.memberByRole('to'),
 
22190                     v = relation.memberByRole('via');
 
22192                 if (f && f.id === turn.from.way &&
 
22193                     v && v.id === turn.via.node &&
 
22194                     t && t.id === turn.to.way) {
 
22195                     turn.restriction = relation.id;
 
22196                 } else if (/^only_/.test(relation.tags.restriction) &&
 
22197                     f && f.id === turn.from.way &&
 
22198                     v && v.id === turn.via.node &&
 
22199                     t && t.id !== turn.to.way) {
 
22200                     turn.restriction = relation.id;
 
22201                     turn.indirect_restriction = true;
 
22205             return iD.geo.Turn(turn);
 
22210                 way: start.id.split(/-(a|b)/)[0]
 
22212             via = { node: vertex.id },
 
22215         _.each(highways, function(end, adjacentNodeId) {
 
22220             if (end.first() !== vertex.id && end.tags.oneway !== 'yes') {
 
22221                 turns.push(withRestriction({
 
22225                         node: adjacentNodeId,
 
22226                         way: end.id.split(/-(a|b)/)[0]
 
22232             if (end.last() !== vertex.id && end.tags.oneway !== '-1') {
 
22233                 turns.push(withRestriction({
 
22237                         node: adjacentNodeId,
 
22238                         way: end.id.split(/-(a|b)/)[0]
 
22246         if (start.tags.oneway !== 'yes' && start.tags.oneway !== '-1') {
 
22247             turns.push(withRestriction({
 
22258     return intersection;
 
22262 iD.geo.inferRestriction = function(graph, from, via, to, projection) {
 
22263     var fromWay = graph.entity(from.way),
 
22264         fromNode = graph.entity(from.node),
 
22265         toWay = graph.entity(to.way),
 
22266         toNode = graph.entity(to.node),
 
22267         viaNode = graph.entity(via.node),
 
22268         fromOneWay = (fromWay.tags.oneway === 'yes' && fromWay.last() === via.node) ||
 
22269             (fromWay.tags.oneway === '-1' && fromWay.first() === via.node),
 
22270         toOneWay = (toWay.tags.oneway === 'yes' && toWay.first() === via.node) ||
 
22271             (toWay.tags.oneway === '-1' && toWay.last() === via.node),
 
22272         angle = iD.geo.angle(viaNode, fromNode, projection) -
 
22273                 iD.geo.angle(viaNode, toNode, projection);
 
22275     angle = angle * 180 / Math.PI;
 
22280     if (fromNode === toNode)
 
22281         return 'no_u_turn';
 
22282     if ((angle < 23 || angle > 336) && fromOneWay && toOneWay)
 
22283         return 'no_u_turn';
 
22285         return 'no_right_turn';
 
22287         return 'no_left_turn';
 
22289     return 'no_straight_on';
 
22291 // For fixing up rendering of multipolygons with tags on the outer member.
 
22292 // https://github.com/openstreetmap/iD/issues/613
 
22293 iD.geo.isSimpleMultipolygonOuterMember = function(entity, graph) {
 
22294     if (entity.type !== 'way')
 
22297     var parents = graph.parentRelations(entity);
 
22298     if (parents.length !== 1)
 
22301     var parent = parents[0];
 
22302     if (!parent.isMultipolygon() || Object.keys(parent.tags).length > 1)
 
22305     var members = parent.members, member;
 
22306     for (var i = 0; i < members.length; i++) {
 
22307         member = members[i];
 
22308         if (member.id === entity.id && member.role && member.role !== 'outer')
 
22309             return false; // Not outer member
 
22310         if (member.id !== entity.id && (!member.role || member.role === 'outer'))
 
22311             return false; // Not a simple multipolygon
 
22317 iD.geo.simpleMultipolygonOuterMember = function(entity, graph) {
 
22318     if (entity.type !== 'way')
 
22321     var parents = graph.parentRelations(entity);
 
22322     if (parents.length !== 1)
 
22325     var parent = parents[0];
 
22326     if (!parent.isMultipolygon() || Object.keys(parent.tags).length > 1)
 
22329     var members = parent.members, member, outerMember;
 
22330     for (var i = 0; i < members.length; i++) {
 
22331         member = members[i];
 
22332         if (!member.role || member.role === 'outer') {
 
22334                 return false; // Not a simple multipolygon
 
22335             outerMember = member;
 
22339     return outerMember && graph.hasEntity(outerMember.id);
 
22342 // Join `array` into sequences of connecting ways.
 
22344 // Segments which share identical start/end nodes will, as much as possible,
 
22345 // be connected with each other.
 
22347 // The return value is a nested array. Each constituent array contains elements
 
22348 // of `array` which have been determined to connect. Each consitituent array
 
22349 // also has a `nodes` property whose value is an ordered array of member nodes,
 
22350 // with appropriate order reversal and start/end coordinate de-duplication.
 
22352 // Members of `array` must have, at minimum, `type` and `id` properties.
 
22353 // Thus either an array of `iD.Way`s or a relation member array may be
 
22356 // If an member has a `tags` property, its tags will be reversed via
 
22357 // `iD.actions.Reverse` in the output.
 
22359 // Incomplete members (those for which `graph.hasEntity(element.id)` returns
 
22360 // false) and non-way members are ignored.
 
22362 iD.geo.joinWays = function(array, graph) {
 
22363     var joined = [], member, current, nodes, first, last, i, how, what;
 
22365     array = array.filter(function(member) {
 
22366         return member.type === 'way' && graph.hasEntity(member.id);
 
22369     function resolve(member) {
 
22370         return graph.childNodes(graph.entity(member.id));
 
22373     function reverse(member) {
 
22374         return member.tags ? iD.actions.Reverse(member.id, {reverseOneway: true})(graph).entity(member.id) : member;
 
22377     while (array.length) {
 
22378         member = array.shift();
 
22379         current = [member];
 
22380         current.nodes = nodes = resolve(member).slice();
 
22381         joined.push(current);
 
22383         while (array.length && _.first(nodes) !== _.last(nodes)) {
 
22384             first = _.first(nodes);
 
22385             last  = _.last(nodes);
 
22387             for (i = 0; i < array.length; i++) {
 
22389                 what = resolve(member);
 
22391                 if (last === _.first(what)) {
 
22393                     what = what.slice(1);
 
22395                 } else if (last === _.last(what)) {
 
22397                     what = what.slice(0, -1).reverse();
 
22398                     member = reverse(member);
 
22400                 } else if (first === _.last(what)) {
 
22401                     how  = nodes.unshift;
 
22402                     what = what.slice(0, -1);
 
22404                 } else if (first === _.first(what)) {
 
22405                     how  = nodes.unshift;
 
22406                     what = what.slice(1).reverse();
 
22407                     member = reverse(member);
 
22415                 break; // No more joinable ways.
 
22417             how.apply(current, [member]);
 
22418             how.apply(nodes, what);
 
22420             array.splice(i, 1);
 
22427     Bypasses features of D3's default projection stream pipeline that are unnecessary:
 
22428     * Antimeridian clipping
 
22429     * Spherical rotation
 
22432 iD.geo.RawMercator = function () {
 
22433     var project = d3.geo.mercator.raw,
 
22434         k = 512 / Math.PI, // scale
 
22435         x = 0, y = 0, // translate
 
22436         clipExtent = [[0, 0], [0, 0]];
 
22438     function projection(point) {
 
22439         point = project(point[0] * Math.PI / 180, point[1] * Math.PI / 180);
 
22440         return [point[0] * k + x, y - point[1] * k];
 
22443     projection.invert = function(point) {
 
22444         point = project.invert((point[0] - x) / k, (y - point[1]) / k);
 
22445         return point && [point[0] * 180 / Math.PI, point[1] * 180 / Math.PI];
 
22448     projection.scale = function(_) {
 
22449         if (!arguments.length) return k;
 
22454     projection.translate = function(_) {
 
22455         if (!arguments.length) return [x, y];
 
22461     projection.clipExtent = function(_) {
 
22462         if (!arguments.length) return clipExtent;
 
22467     projection.stream = d3.geo.transform({
 
22468         point: function(x, y) {
 
22469             x = projection([x, y]);
 
22470             this.stream.point(x[0], x[1]);
 
22477 iD.actions.AddEntity = function(way) {
 
22478     return function(graph) {
 
22479         return graph.replace(way);
 
22482 iD.actions.AddMember = function(relationId, member, memberIndex) {
 
22483     return function(graph) {
 
22484         var relation = graph.entity(relationId);
 
22486         if (isNaN(memberIndex) && member.type === 'way') {
 
22487             var members = relation.indexedMembers();
 
22488             members.push(member);
 
22490             var joined = iD.geo.joinWays(members, graph);
 
22491             for (var i = 0; i < joined.length; i++) {
 
22492                 var segment = joined[i];
 
22493                 for (var j = 0; j < segment.length && segment.length >= 2; j++) {
 
22494                     if (segment[j] !== member)
 
22498                         memberIndex = segment[j + 1].index;
 
22499                     } else if (j === segment.length - 1) {
 
22500                         memberIndex = segment[j - 1].index + 1;
 
22502                         memberIndex = Math.min(segment[j - 1].index + 1, segment[j + 1].index + 1);
 
22508         return graph.replace(relation.addMember(member, memberIndex));
 
22511 iD.actions.AddMidpoint = function(midpoint, node) {
 
22512     return function(graph) {
 
22513         graph = graph.replace(node.move(midpoint.loc));
 
22515         var parents = _.intersection(
 
22516             graph.parentWays(graph.entity(midpoint.edge[0])),
 
22517             graph.parentWays(graph.entity(midpoint.edge[1])));
 
22519         parents.forEach(function(way) {
 
22520             for (var i = 0; i < way.nodes.length - 1; i++) {
 
22521                 if (iD.geo.edgeEqual([way.nodes[i], way.nodes[i + 1]], midpoint.edge)) {
 
22522                     graph = graph.replace(graph.entity(way.id).addNode(node.id, i + 1));
 
22524                     // Add only one midpoint on doubled-back segments,
 
22525                     // turning them into self-intersections.
 
22534 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as
 
22535 iD.actions.AddVertex = function(wayId, nodeId, index) {
 
22536     return function(graph) {
 
22537         return graph.replace(graph.entity(wayId).addNode(nodeId, index));
 
22540 iD.actions.ChangeMember = function(relationId, member, memberIndex) {
 
22541     return function(graph) {
 
22542         return graph.replace(graph.entity(relationId).updateMember(member, memberIndex));
 
22545 iD.actions.ChangePreset = function(entityId, oldPreset, newPreset) {
 
22546     return function(graph) {
 
22547         var entity = graph.entity(entityId),
 
22548             geometry = entity.geometry(graph),
 
22549             tags = entity.tags;
 
22551         if (oldPreset) tags = oldPreset.removeTags(tags, geometry);
 
22552         if (newPreset) tags = newPreset.applyTags(tags, geometry);
 
22554         return graph.replace(entity.update({tags: tags}));
 
22557 iD.actions.ChangeTags = function(entityId, tags) {
 
22558     return function(graph) {
 
22559         var entity = graph.entity(entityId);
 
22560         return graph.replace(entity.update({tags: tags}));
 
22563 iD.actions.Circularize = function(wayId, projection, maxAngle) {
 
22564     maxAngle = (maxAngle || 20) * Math.PI / 180;
 
22566     var action = function(graph) {
 
22567         var way = graph.entity(wayId);
 
22569         if (!way.isConvex(graph)) {
 
22570             graph = action.makeConvex(graph);
 
22573         var nodes = _.uniq(graph.childNodes(way)),
 
22574             keyNodes = nodes.filter(function(n) { return graph.parentWays(n).length !== 1; }),
 
22575             points = nodes.map(function(n) { return projection(n.loc); }),
 
22576             keyPoints = keyNodes.map(function(n) { return projection(n.loc); }),
 
22577             centroid = (points.length === 2) ? iD.geo.interp(points[0], points[1], 0.5) : d3.geom.polygon(points).centroid(),
 
22578             radius = d3.median(points, function(p) { return iD.geo.euclideanDistance(centroid, p); }),
 
22579             sign = d3.geom.polygon(points).area() > 0 ? 1 : -1,
 
22582         // we need atleast two key nodes for the algorithm to work
 
22583         if (!keyNodes.length) {
 
22584             keyNodes = [nodes[0]];
 
22585             keyPoints = [points[0]];
 
22588         if (keyNodes.length === 1) {
 
22589             var index = nodes.indexOf(keyNodes[0]),
 
22590                 oppositeIndex = Math.floor((index + nodes.length / 2) % nodes.length);
 
22592             keyNodes.push(nodes[oppositeIndex]);
 
22593             keyPoints.push(points[oppositeIndex]);
 
22596         // key points and nodes are those connected to the ways,
 
22597         // they are projected onto the circle, inbetween nodes are moved
 
22598         // to constant intervals between key nodes, extra inbetween nodes are
 
22599         // added if necessary.
 
22600         for (var i = 0; i < keyPoints.length; i++) {
 
22601             var nextKeyNodeIndex = (i + 1) % keyNodes.length,
 
22602                 startNode = keyNodes[i],
 
22603                 endNode = keyNodes[nextKeyNodeIndex],
 
22604                 startNodeIndex = nodes.indexOf(startNode),
 
22605                 endNodeIndex = nodes.indexOf(endNode),
 
22606                 numberNewPoints = -1,
 
22607                 indexRange = endNodeIndex - startNodeIndex,
 
22608                 distance, totalAngle, eachAngle, startAngle, endAngle,
 
22609                 angle, loc, node, j,
 
22610                 inBetweenNodes = [];
 
22612             if (indexRange < 0) {
 
22613                 indexRange += nodes.length;
 
22616             // position this key node
 
22617             distance = iD.geo.euclideanDistance(centroid, keyPoints[i]);
 
22618             if (distance === 0) { distance = 1e-4; }
 
22620                 centroid[0] + (keyPoints[i][0] - centroid[0]) / distance * radius,
 
22621                 centroid[1] + (keyPoints[i][1] - centroid[1]) / distance * radius];
 
22622             graph = graph.replace(keyNodes[i].move(projection.invert(keyPoints[i])));
 
22624             // figure out the between delta angle we want to match to
 
22625             startAngle = Math.atan2(keyPoints[i][1] - centroid[1], keyPoints[i][0] - centroid[0]);
 
22626             endAngle = Math.atan2(keyPoints[nextKeyNodeIndex][1] - centroid[1], keyPoints[nextKeyNodeIndex][0] - centroid[0]);
 
22627             totalAngle = endAngle - startAngle;
 
22629             // detects looping around -pi/pi
 
22630             if (totalAngle * sign > 0) {
 
22631                 totalAngle = -sign * (2 * Math.PI - Math.abs(totalAngle));
 
22636                 eachAngle = totalAngle / (indexRange + numberNewPoints);
 
22637             } while (Math.abs(eachAngle) > maxAngle);
 
22639             // move existing points
 
22640             for (j = 1; j < indexRange; j++) {
 
22641                 angle = startAngle + j * eachAngle;
 
22642                 loc = projection.invert([
 
22643                     centroid[0] + Math.cos(angle)*radius,
 
22644                     centroid[1] + Math.sin(angle)*radius]);
 
22646                 node = nodes[(j + startNodeIndex) % nodes.length].move(loc);
 
22647                 graph = graph.replace(node);
 
22650             // add new inbetween nodes if necessary
 
22651             for (j = 0; j < numberNewPoints; j++) {
 
22652                 angle = startAngle + (indexRange + j) * eachAngle;
 
22653                 loc = projection.invert([
 
22654                     centroid[0] + Math.cos(angle) * radius,
 
22655                     centroid[1] + Math.sin(angle) * radius]);
 
22657                 node = iD.Node({loc: loc});
 
22658                 graph = graph.replace(node);
 
22660                 nodes.splice(endNodeIndex + j, 0, node);
 
22661                 inBetweenNodes.push(node.id);
 
22664             // Check for other ways that share these keyNodes..
 
22665             // If keyNodes are adjacent in both ways,
 
22666             // we can add inBetween nodes to that shared way too..
 
22667             if (indexRange === 1 && inBetweenNodes.length) {
 
22668                 var startIndex1 = way.nodes.lastIndexOf(startNode.id),
 
22669                     endIndex1 = way.nodes.lastIndexOf(endNode.id),
 
22670                     wayDirection1 = (endIndex1 - startIndex1);
 
22671                 if (wayDirection1 < -1) { wayDirection1 = 1; }
 
22673                 /* eslint-disable no-loop-func */
 
22674                 _.each(_.without(graph.parentWays(keyNodes[i]), way), function(sharedWay) {
 
22675                     if (sharedWay.areAdjacent(startNode.id, endNode.id)) {
 
22676                         var startIndex2 = sharedWay.nodes.lastIndexOf(startNode.id),
 
22677                             endIndex2 = sharedWay.nodes.lastIndexOf(endNode.id),
 
22678                             wayDirection2 = (endIndex2 - startIndex2),
 
22679                             insertAt = endIndex2;
 
22680                         if (wayDirection2 < -1) { wayDirection2 = 1; }
 
22682                         if (wayDirection1 !== wayDirection2) {
 
22683                             inBetweenNodes.reverse();
 
22684                             insertAt = startIndex2;
 
22686                         for (j = 0; j < inBetweenNodes.length; j++) {
 
22687                             sharedWay = sharedWay.addNode(inBetweenNodes[j], insertAt + j);
 
22689                         graph = graph.replace(sharedWay);
 
22692                 /* eslint-enable no-loop-func */
 
22697         // update the way to have all the new nodes
 
22698         ids = nodes.map(function(n) { return n.id; });
 
22701         way = way.update({nodes: ids});
 
22702         graph = graph.replace(way);
 
22707     action.makeConvex = function(graph) {
 
22708         var way = graph.entity(wayId),
 
22709             nodes = _.uniq(graph.childNodes(way)),
 
22710             points = nodes.map(function(n) { return projection(n.loc); }),
 
22711             sign = d3.geom.polygon(points).area() > 0 ? 1 : -1,
 
22712             hull = d3.geom.hull(points);
 
22714         // D3 convex hulls go counterclockwise..
 
22720         for (var i = 0; i < hull.length - 1; i++) {
 
22721             var startIndex = points.indexOf(hull[i]),
 
22722                 endIndex = points.indexOf(hull[i+1]),
 
22723                 indexRange = (endIndex - startIndex);
 
22725             if (indexRange < 0) {
 
22726                 indexRange += nodes.length;
 
22729             // move interior nodes to the surface of the convex hull..
 
22730             for (var j = 1; j < indexRange; j++) {
 
22731                 var point = iD.geo.interp(hull[i], hull[i+1], j / indexRange),
 
22732                     node = nodes[(j + startIndex) % nodes.length].move(projection.invert(point));
 
22733                 graph = graph.replace(node);
 
22739     action.disabled = function(graph) {
 
22740         if (!graph.entity(wayId).isClosed())
 
22741             return 'not_closed';
 
22746 // Connect the ways at the given nodes.
 
22748 // The last node will survive. All other nodes will be replaced with
 
22749 // the surviving node in parent ways, and then removed.
 
22751 // Tags and relation memberships of of non-surviving nodes are merged
 
22752 // to the survivor.
 
22754 // This is the inverse of `iD.actions.Disconnect`.
 
22757 //   https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeNodesAction.as
 
22758 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/MergeNodesAction.java
 
22760 iD.actions.Connect = function(nodeIds) {
 
22761     return function(graph) {
 
22762         var survivor = graph.entity(_.last(nodeIds));
 
22764         for (var i = 0; i < nodeIds.length - 1; i++) {
 
22765             var node = graph.entity(nodeIds[i]);
 
22767             /* eslint-disable no-loop-func */
 
22768             graph.parentWays(node).forEach(function(parent) {
 
22769                 if (!parent.areAdjacent(node.id, survivor.id)) {
 
22770                     graph = graph.replace(parent.replaceNode(node.id, survivor.id));
 
22774             graph.parentRelations(node).forEach(function(parent) {
 
22775                 graph = graph.replace(parent.replaceMember(node, survivor));
 
22777             /* eslint-enable no-loop-func */
 
22779             survivor = survivor.mergeTags(node.tags);
 
22780             graph = iD.actions.DeleteNode(node.id)(graph);
 
22783         graph = graph.replace(survivor);
 
22788 iD.actions.CopyEntities = function(ids, fromGraph) {
 
22791     var action = function(graph) {
 
22792         ids.forEach(function(id) {
 
22793             fromGraph.entity(id).copy(fromGraph, copies);
 
22796         for (var id in copies) {
 
22797             graph = graph.replace(copies[id]);
 
22803     action.copies = function() {
 
22809 iD.actions.DeleteMember = function(relationId, memberIndex) {
 
22810     return function(graph) {
 
22811         var relation = graph.entity(relationId)
 
22812             .removeMember(memberIndex);
 
22814         graph = graph.replace(relation);
 
22816         if (relation.isDegenerate())
 
22817             graph = iD.actions.DeleteRelation(relation.id)(graph);
 
22822 iD.actions.DeleteMultiple = function(ids) {
 
22824         way: iD.actions.DeleteWay,
 
22825         node: iD.actions.DeleteNode,
 
22826         relation: iD.actions.DeleteRelation
 
22829     var action = function(graph) {
 
22830         ids.forEach(function(id) {
 
22831             if (graph.hasEntity(id)) { // It may have been deleted aready.
 
22832                 graph = actions[graph.entity(id).type](id)(graph);
 
22839     action.disabled = function(graph) {
 
22840         for (var i = 0; i < ids.length; i++) {
 
22842                 disabled = actions[graph.entity(id).type](id).disabled(graph);
 
22843             if (disabled) return disabled;
 
22849 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteNodeAction.as
 
22850 iD.actions.DeleteNode = function(nodeId) {
 
22851     var action = function(graph) {
 
22852         var node = graph.entity(nodeId);
 
22854         graph.parentWays(node)
 
22855             .forEach(function(parent) {
 
22856                 parent = parent.removeNode(nodeId);
 
22857                 graph = graph.replace(parent);
 
22859                 if (parent.isDegenerate()) {
 
22860                     graph = iD.actions.DeleteWay(parent.id)(graph);
 
22864         graph.parentRelations(node)
 
22865             .forEach(function(parent) {
 
22866                 parent = parent.removeMembersWithID(nodeId);
 
22867                 graph = graph.replace(parent);
 
22869                 if (parent.isDegenerate()) {
 
22870                     graph = iD.actions.DeleteRelation(parent.id)(graph);
 
22874         return graph.remove(node);
 
22877     action.disabled = function() {
 
22883 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteRelationAction.as
 
22884 iD.actions.DeleteRelation = function(relationId) {
 
22885     function deleteEntity(entity, graph) {
 
22886         return !graph.parentWays(entity).length &&
 
22887             !graph.parentRelations(entity).length &&
 
22888             !entity.hasInterestingTags();
 
22891     var action = function(graph) {
 
22892         var relation = graph.entity(relationId);
 
22894         graph.parentRelations(relation)
 
22895             .forEach(function(parent) {
 
22896                 parent = parent.removeMembersWithID(relationId);
 
22897                 graph = graph.replace(parent);
 
22899                 if (parent.isDegenerate()) {
 
22900                     graph = iD.actions.DeleteRelation(parent.id)(graph);
 
22904         _.uniq(_.map(relation.members, 'id')).forEach(function(memberId) {
 
22905             graph = graph.replace(relation.removeMembersWithID(memberId));
 
22907             var entity = graph.entity(memberId);
 
22908             if (deleteEntity(entity, graph)) {
 
22909                 graph = iD.actions.DeleteMultiple([memberId])(graph);
 
22913         return graph.remove(relation);
 
22916     action.disabled = function(graph) {
 
22917         if (!graph.entity(relationId).isComplete(graph))
 
22918             return 'incomplete_relation';
 
22923 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteWayAction.as
 
22924 iD.actions.DeleteWay = function(wayId) {
 
22925     function deleteNode(node, graph) {
 
22926         return !graph.parentWays(node).length &&
 
22927             !graph.parentRelations(node).length &&
 
22928             !node.hasInterestingTags();
 
22931     var action = function(graph) {
 
22932         var way = graph.entity(wayId);
 
22934         graph.parentRelations(way)
 
22935             .forEach(function(parent) {
 
22936                 parent = parent.removeMembersWithID(wayId);
 
22937                 graph = graph.replace(parent);
 
22939                 if (parent.isDegenerate()) {
 
22940                     graph = iD.actions.DeleteRelation(parent.id)(graph);
 
22944         _.uniq(way.nodes).forEach(function(nodeId) {
 
22945             graph = graph.replace(way.removeNode(nodeId));
 
22947             var node = graph.entity(nodeId);
 
22948             if (deleteNode(node, graph)) {
 
22949                 graph = graph.remove(node);
 
22953         return graph.remove(way);
 
22956     action.disabled = function(graph) {
 
22957         var disabled = false;
 
22959         graph.parentRelations(graph.entity(wayId)).forEach(function(parent) {
 
22960             var type = parent.tags.type,
 
22961                 role = parent.memberById(wayId).role || 'outer';
 
22962             if (type === 'route' || type === 'boundary' || (type === 'multipolygon' && role === 'outer')) {
 
22963                 disabled = 'part_of_relation';
 
22972 iD.actions.DeprecateTags = function(entityId) {
 
22973     return function(graph) {
 
22974         var entity = graph.entity(entityId),
 
22975             newtags = _.clone(entity.tags),
 
22979         // This handles deprecated tags with a single condition
 
22980         for (var i = 0; i < iD.data.deprecated.length; i++) {
 
22982             rule = iD.data.deprecated[i];
 
22983             var match = _.toPairs(rule.old)[0],
 
22984                 replacements = rule.replace ? _.toPairs(rule.replace) : null;
 
22986             if (entity.tags[match[0]] && match[1] === '*') {
 
22988                 var value = entity.tags[match[0]];
 
22989                 if (replacements && !newtags[replacements[0][0]]) {
 
22990                     newtags[replacements[0][0]] = value;
 
22992                 delete newtags[match[0]];
 
22995             } else if (entity.tags[match[0]] === match[1]) {
 
22996                 newtags = _.assign({}, rule.replace || {}, _.omit(newtags, match[0]));
 
23002             return graph.replace(entity.update({tags: newtags}));
 
23008 iD.actions.DiscardTags = function(difference) {
 
23009     return function(graph) {
 
23010         function discardTags(entity) {
 
23011             if (!_.isEmpty(entity.tags)) {
 
23013                 _.each(entity.tags, function(v, k) {
 
23014                     if (v) tags[k] = v;
 
23017                 graph = graph.replace(entity.update({
 
23018                     tags: _.omit(tags, iD.data.discarded)
 
23023         difference.modified().forEach(discardTags);
 
23024         difference.created().forEach(discardTags);
 
23029 // Disconect the ways at the given node.
 
23031 // Optionally, disconnect only the given ways.
 
23033 // For testing convenience, accepts an ID to assign to the (first) new node.
 
23034 // Normally, this will be undefined and the way will automatically
 
23035 // be assigned a new ID.
 
23037 // This is the inverse of `iD.actions.Connect`.
 
23040 //   https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as
 
23041 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/UnGlueAction.java
 
23043 iD.actions.Disconnect = function(nodeId, newNodeId) {
 
23046     var action = function(graph) {
 
23047         var node = graph.entity(nodeId),
 
23048             connections = action.connections(graph);
 
23050         connections.forEach(function(connection) {
 
23051             var way = graph.entity(connection.wayID),
 
23052                 newNode = iD.Node({id: newNodeId, loc: node.loc, tags: node.tags});
 
23054             graph = graph.replace(newNode);
 
23055             if (connection.index === 0 && way.isArea()) {
 
23056                 // replace shared node with shared node..
 
23057                 graph = graph.replace(way.replaceNode(way.nodes[0], newNode.id));
 
23059                 // replace shared node with multiple new nodes..
 
23060                 graph = graph.replace(way.updateNode(newNode.id, connection.index));
 
23067     action.connections = function(graph) {
 
23068         var candidates = [],
 
23070             parentWays = graph.parentWays(graph.entity(nodeId));
 
23072         parentWays.forEach(function(way) {
 
23073             if (wayIds && wayIds.indexOf(way.id) === -1) {
 
23077             if (way.isArea() && (way.nodes[0] === nodeId)) {
 
23078                 candidates.push({wayID: way.id, index: 0});
 
23080                 way.nodes.forEach(function(waynode, index) {
 
23081                     if (waynode === nodeId) {
 
23082                         candidates.push({wayID: way.id, index: index});
 
23088         return keeping ? candidates : candidates.slice(1);
 
23091     action.disabled = function(graph) {
 
23092         var connections = action.connections(graph);
 
23093         if (connections.length === 0 || (wayIds && wayIds.length !== connections.length))
 
23094             return 'not_connected';
 
23096         var parentWays = graph.parentWays(graph.entity(nodeId)),
 
23097             seenRelationIds = {},
 
23100         parentWays.forEach(function(way) {
 
23101             if (wayIds && wayIds.indexOf(way.id) === -1)
 
23104             var relations = graph.parentRelations(way);
 
23105             relations.forEach(function(relation) {
 
23106                 if (relation.id in seenRelationIds) {
 
23107                     sharedRelation = relation;
 
23109                     seenRelationIds[relation.id] = true;
 
23114         if (sharedRelation)
 
23118     action.limitWays = function(_) {
 
23119         if (!arguments.length) return wayIds;
 
23126 // Join ways at the end node they share.
 
23128 // This is the inverse of `iD.actions.Split`.
 
23131 //   https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeWaysAction.as
 
23132 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/CombineWayAction.java
 
23134 iD.actions.Join = function(ids) {
 
23136     function groupEntitiesByGeometry(graph) {
 
23137         var entities = ids.map(function(id) { return graph.entity(id); });
 
23138         return _.extend({line: []}, _.groupBy(entities, function(entity) { return entity.geometry(graph); }));
 
23141     var action = function(graph) {
 
23142         var ways = ids.map(graph.entity, graph),
 
23143             survivor = ways[0];
 
23145         // Prefer to keep an existing way.
 
23146         for (var i = 0; i < ways.length; i++) {
 
23147             if (!ways[i].isNew()) {
 
23148                 survivor = ways[i];
 
23153         var joined = iD.geo.joinWays(ways, graph)[0];
 
23155         survivor = survivor.update({nodes: _.map(joined.nodes, 'id')});
 
23156         graph = graph.replace(survivor);
 
23158         joined.forEach(function(way) {
 
23159             if (way.id === survivor.id)
 
23162             graph.parentRelations(way).forEach(function(parent) {
 
23163                 graph = graph.replace(parent.replaceMember(way, survivor));
 
23166             survivor = survivor.mergeTags(way.tags);
 
23168             graph = graph.replace(survivor);
 
23169             graph = iD.actions.DeleteWay(way.id)(graph);
 
23175     action.disabled = function(graph) {
 
23176         var geometries = groupEntitiesByGeometry(graph);
 
23177         if (ids.length < 2 || ids.length !== geometries.line.length)
 
23178             return 'not_eligible';
 
23180         var joined = iD.geo.joinWays(ids.map(graph.entity, graph), graph);
 
23181         if (joined.length > 1)
 
23182             return 'not_adjacent';
 
23184         var nodeIds = _.map(joined[0].nodes, 'id').slice(1, -1),
 
23187             conflicting = false;
 
23189         joined[0].forEach(function(way) {
 
23190             var parents = graph.parentRelations(way);
 
23191             parents.forEach(function(parent) {
 
23192                 if (parent.isRestriction() && parent.members.some(function(m) { return nodeIds.indexOf(m.id) >= 0; }))
 
23196             for (var k in way.tags) {
 
23197                 if (!(k in tags)) {
 
23198                     tags[k] = way.tags[k];
 
23199                 } else if (tags[k] && iD.interestingTag(k) && tags[k] !== way.tags[k]) {
 
23200                     conflicting = true;
 
23206             return 'restriction';
 
23209             return 'conflicting_tags';
 
23214 iD.actions.Merge = function(ids) {
 
23215     function groupEntitiesByGeometry(graph) {
 
23216         var entities = ids.map(function(id) { return graph.entity(id); });
 
23217         return _.extend({point: [], area: [], line: [], relation: []},
 
23218             _.groupBy(entities, function(entity) { return entity.geometry(graph); }));
 
23221     var action = function(graph) {
 
23222         var geometries = groupEntitiesByGeometry(graph),
 
23223             target = geometries.area[0] || geometries.line[0],
 
23224             points = geometries.point;
 
23226         points.forEach(function(point) {
 
23227             target = target.mergeTags(point.tags);
 
23229             graph.parentRelations(point).forEach(function(parent) {
 
23230                 graph = graph.replace(parent.replaceMember(point, target));
 
23233             graph = graph.remove(point);
 
23236         graph = graph.replace(target);
 
23241     action.disabled = function(graph) {
 
23242         var geometries = groupEntitiesByGeometry(graph);
 
23243         if (geometries.point.length === 0 ||
 
23244             (geometries.area.length + geometries.line.length) !== 1 ||
 
23245             geometries.relation.length !== 0)
 
23246             return 'not_eligible';
 
23251 iD.actions.MergePolygon = function(ids, newRelationId) {
 
23253     function groupEntities(graph) {
 
23254         var entities = ids.map(function (id) { return graph.entity(id); });
 
23259             }, _.groupBy(entities, function(entity) {
 
23260                 if (entity.type === 'way' && entity.isClosed()) {
 
23261                     return 'closedWay';
 
23262                 } else if (entity.type === 'relation' && entity.isMultipolygon()) {
 
23263                     return 'multipolygon';
 
23270     var action = function(graph) {
 
23271         var entities = groupEntities(graph);
 
23273         // An array representing all the polygons that are part of the multipolygon.
 
23275         // Each element is itself an array of objects with an id property, and has a
 
23276         // locs property which is an array of the locations forming the polygon.
 
23277         var polygons = entities.multipolygon.reduce(function(polygons, m) {
 
23278             return polygons.concat(iD.geo.joinWays(m.members, graph));
 
23279         }, []).concat(entities.closedWay.map(function(d) {
 
23280             var member = [{id: d.id}];
 
23281             member.nodes = graph.childNodes(d);
 
23285         // contained is an array of arrays of boolean values,
 
23286         // where contained[j][k] is true iff the jth way is
 
23287         // contained by the kth way.
 
23288         var contained = polygons.map(function(w, i) {
 
23289             return polygons.map(function(d, n) {
 
23290                 if (i === n) return null;
 
23291                 return iD.geo.polygonContainsPolygon(
 
23292                     _.map(d.nodes, 'loc'),
 
23293                     _.map(w.nodes, 'loc'));
 
23297         // Sort all polygons as either outer or inner ways
 
23301         while (polygons.length) {
 
23302             extractUncontained(polygons);
 
23303             polygons = polygons.filter(isContained);
 
23304             contained = contained.filter(isContained).map(filterContained);
 
23307         function isContained(d, i) {
 
23308             return _.some(contained[i]);
 
23311         function filterContained(d) {
 
23312             return d.filter(isContained);
 
23315         function extractUncontained(polygons) {
 
23316             polygons.forEach(function(d, i) {
 
23317                 if (!isContained(d, i)) {
 
23318                     d.forEach(function(member) {
 
23322                             role: outer ? 'outer' : 'inner'
 
23330         // Move all tags to one relation
 
23331         var relation = entities.multipolygon[0] ||
 
23332             iD.Relation({ id: newRelationId, tags: { type: 'multipolygon' }});
 
23334         entities.multipolygon.slice(1).forEach(function(m) {
 
23335             relation = relation.mergeTags(m.tags);
 
23336             graph = graph.remove(m);
 
23339         entities.closedWay.forEach(function(way) {
 
23340             function isThisOuter(m) {
 
23341                 return m.id === way.id && m.role !== 'inner';
 
23343             if (members.some(isThisOuter)) {
 
23344                 relation = relation.mergeTags(way.tags);
 
23345                 graph = graph.replace(way.update({ tags: {} }));
 
23349         return graph.replace(relation.update({
 
23351             tags: _.omit(relation.tags, 'area')
 
23355     action.disabled = function(graph) {
 
23356         var entities = groupEntities(graph);
 
23357         if (entities.other.length > 0 ||
 
23358             entities.closedWay.length + entities.multipolygon.length < 2)
 
23359             return 'not_eligible';
 
23360         if (!entities.multipolygon.every(function(r) { return r.isComplete(graph); }))
 
23361             return 'incomplete_relation';
 
23366 iD.actions.MergeRemoteChanges = function(id, localGraph, remoteGraph, formatUser) {
 
23367     var option = 'safe',  // 'safe', 'force_local', 'force_remote'
 
23371         return _.isFunction(formatUser) ? formatUser(d) : d;
 
23375     function mergeLocation(remote, target) {
 
23376         function pointEqual(a, b) {
 
23377             var epsilon = 1e-6;
 
23378             return (Math.abs(a[0] - b[0]) < epsilon) && (Math.abs(a[1] - b[1]) < epsilon);
 
23381         if (option === 'force_local' || pointEqual(target.loc, remote.loc)) {
 
23384         if (option === 'force_remote') {
 
23385             return target.update({loc: remote.loc});
 
23388         conflicts.push(t('merge_remote_changes.conflict.location', { user: user(remote.user) }));
 
23393     function mergeNodes(base, remote, target) {
 
23394         if (option === 'force_local' || _.isEqual(target.nodes, remote.nodes)) {
 
23397         if (option === 'force_remote') {
 
23398             return target.update({nodes: remote.nodes});
 
23401         var ccount = conflicts.length,
 
23402             o = base.nodes || [],
 
23403             a = target.nodes || [],
 
23404             b = remote.nodes || [],
 
23406             hunks = Diff3.diff3_merge(a, o, b, true);
 
23408         for (var i = 0; i < hunks.length; i++) {
 
23409             var hunk = hunks[i];
 
23411                 nodes.push.apply(nodes, hunk.ok);
 
23413                 // for all conflicts, we can assume c.a !== c.b
 
23414                 // because `diff3_merge` called with `true` option to exclude false conflicts..
 
23415                 var c = hunk.conflict;
 
23416                 if (_.isEqual(c.o, c.a)) {  // only changed remotely
 
23417                     nodes.push.apply(nodes, c.b);
 
23418                 } else if (_.isEqual(c.o, c.b)) {  // only changed locally
 
23419                     nodes.push.apply(nodes, c.a);
 
23420                 } else {       // changed both locally and remotely
 
23421                     conflicts.push(t('merge_remote_changes.conflict.nodelist', { user: user(remote.user) }));
 
23427         return (conflicts.length === ccount) ? target.update({nodes: nodes}) : target;
 
23431     function mergeChildren(targetWay, children, updates, graph) {
 
23432         function isUsed(node, targetWay) {
 
23433             var parentWays = _.map(graph.parentWays(node), 'id');
 
23434             return node.hasInterestingTags() ||
 
23435                 _.without(parentWays, targetWay.id).length > 0 ||
 
23436                 graph.parentRelations(node).length > 0;
 
23439         var ccount = conflicts.length;
 
23441         for (var i = 0; i < children.length; i++) {
 
23442             var id = children[i],
 
23443                 node = graph.hasEntity(id);
 
23445             // remove unused childNodes..
 
23446             if (targetWay.nodes.indexOf(id) === -1) {
 
23447                 if (node && !isUsed(node, targetWay)) {
 
23448                     updates.removeIds.push(id);
 
23453             // restore used childNodes..
 
23454             var local = localGraph.hasEntity(id),
 
23455                 remote = remoteGraph.hasEntity(id),
 
23458             if (option === 'force_remote' && remote && remote.visible) {
 
23459                 updates.replacements.push(remote);
 
23461             } else if (option === 'force_local' && local) {
 
23462                 target = iD.Entity(local);
 
23464                     target = target.update({ version: remote.version });
 
23466                 updates.replacements.push(target);
 
23468             } else if (option === 'safe' && local && remote && local.version !== remote.version) {
 
23469                 target = iD.Entity(local, { version: remote.version });
 
23470                 if (remote.visible) {
 
23471                     target = mergeLocation(remote, target);
 
23473                     conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) }));
 
23476                 if (conflicts.length !== ccount) break;
 
23477                 updates.replacements.push(target);
 
23485     function updateChildren(updates, graph) {
 
23486         for (var i = 0; i < updates.replacements.length; i++) {
 
23487             graph = graph.replace(updates.replacements[i]);
 
23489         if (updates.removeIds.length) {
 
23490             graph = iD.actions.DeleteMultiple(updates.removeIds)(graph);
 
23496     function mergeMembers(remote, target) {
 
23497         if (option === 'force_local' || _.isEqual(target.members, remote.members)) {
 
23500         if (option === 'force_remote') {
 
23501             return target.update({members: remote.members});
 
23504         conflicts.push(t('merge_remote_changes.conflict.memberlist', { user: user(remote.user) }));
 
23509     function mergeTags(base, remote, target) {
 
23510         function ignoreKey(k) {
 
23511             return _.includes(iD.data.discarded, k);
 
23514         if (option === 'force_local' || _.isEqual(target.tags, remote.tags)) {
 
23517         if (option === 'force_remote') {
 
23518             return target.update({tags: remote.tags});
 
23521         var ccount = conflicts.length,
 
23522             o = base.tags || {},
 
23523             a = target.tags || {},
 
23524             b = remote.tags || {},
 
23525             keys = _.reject(_.union(_.keys(o), _.keys(a), _.keys(b)), ignoreKey),
 
23529         for (var i = 0; i < keys.length; i++) {
 
23532             if (o[k] !== b[k] && a[k] !== b[k]) {    // changed remotely..
 
23533                 if (o[k] !== a[k]) {      // changed locally..
 
23534                     conflicts.push(t('merge_remote_changes.conflict.tags',
 
23535                         { tag: k, local: a[k], remote: b[k], user: user(remote.user) }));
 
23537                 } else {                  // unchanged locally, accept remote change..
 
23538                     if (b.hasOwnProperty(k)) {
 
23548         return (changed && conflicts.length === ccount) ? target.update({tags: tags}) : target;
 
23552     //  `graph.base()` is the common ancestor of the two graphs.
 
23553     //  `localGraph` contains user's edits up to saving
 
23554     //  `remoteGraph` contains remote edits to modified nodes
 
23555     //  `graph` must be a descendent of `localGraph` and may include
 
23556     //      some conflict resolution actions performed on it.
 
23558     //                  --- ... --- `localGraph` -- ... -- `graph`
 
23560     //  `graph.base()` --- ... --- `remoteGraph`
 
23562     var action = function(graph) {
 
23563         var updates = { replacements: [], removeIds: [] },
 
23564             base = graph.base().entities[id],
 
23565             local = localGraph.entity(id),
 
23566             remote = remoteGraph.entity(id),
 
23567             target = iD.Entity(local, { version: remote.version });
 
23570         if (!remote.visible) {
 
23571             if (option === 'force_remote') {
 
23572                 return iD.actions.DeleteMultiple([id])(graph);
 
23574             } else if (option === 'force_local') {
 
23575                 if (target.type === 'way') {
 
23576                     target = mergeChildren(target, _.uniq(local.nodes), updates, graph);
 
23577                     graph = updateChildren(updates, graph);
 
23579                 return graph.replace(target);
 
23582                 conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) }));
 
23583                 return graph;  // do nothing
 
23588         if (target.type === 'node') {
 
23589             target = mergeLocation(remote, target);
 
23591         } else if (target.type === 'way') {
 
23592             // pull in any child nodes that may not be present locally..
 
23593             graph.rebase(remoteGraph.childNodes(remote), [graph], false);
 
23594             target = mergeNodes(base, remote, target);
 
23595             target = mergeChildren(target, _.union(local.nodes, remote.nodes), updates, graph);
 
23597         } else if (target.type === 'relation') {
 
23598             target = mergeMembers(remote, target);
 
23601         target = mergeTags(base, remote, target);
 
23603         if (!conflicts.length) {
 
23604             graph = updateChildren(updates, graph).replace(target);
 
23610     action.withOption = function(opt) {
 
23615     action.conflicts = function() {
 
23621 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
 
23622 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
 
23623 iD.actions.Move = function(moveIds, tryDelta, projection, cache) {
 
23624     var delta = tryDelta;
 
23626     function vecAdd(a, b) { return [a[0] + b[0], a[1] + b[1]]; }
 
23627     function vecSub(a, b) { return [a[0] - b[0], a[1] - b[1]]; }
 
23629     function setupCache(graph) {
 
23630         function canMove(nodeId) {
 
23631             var parents = _.map(graph.parentWays(graph.entity(nodeId)), 'id');
 
23632             if (parents.length < 3) return true;
 
23634             // Don't move a vertex where >2 ways meet, unless all parentWays are moving too..
 
23635             var parentsMoving = _.every(parents, function(id) { return cache.moving[id]; });
 
23636             if (!parentsMoving) delete cache.moving[nodeId];
 
23638             return parentsMoving;
 
23641         function cacheEntities(ids) {
 
23642             _.each(ids, function(id) {
 
23643                 if (cache.moving[id]) return;
 
23644                 cache.moving[id] = true;
 
23646                 var entity = graph.hasEntity(id);
 
23647                 if (!entity) return;
 
23649                 if (entity.type === 'node') {
 
23650                     cache.nodes.push(id);
 
23651                     cache.startLoc[id] = entity.loc;
 
23652                 } else if (entity.type === 'way') {
 
23653                     cache.ways.push(id);
 
23654                     cacheEntities(entity.nodes);
 
23656                     cacheEntities(_.map(entity.members, 'id'));
 
23661         function cacheIntersections(ids) {
 
23662             function isEndpoint(way, id) { return !way.isClosed() && !!way.affix(id); }
 
23664             _.each(ids, function(id) {
 
23665                 // consider only intersections with 1 moved and 1 unmoved way.
 
23666                 _.each(graph.childNodes(graph.entity(id)), function(node) {
 
23667                     var parents = graph.parentWays(node);
 
23668                     if (parents.length !== 2) return;
 
23670                     var moved = graph.entity(id),
 
23671                         unmoved = _.find(parents, function(way) { return !cache.moving[way.id]; });
 
23672                     if (!unmoved) return;
 
23674                     // exclude ways that are overly connected..
 
23675                     if (_.intersection(moved.nodes, unmoved.nodes).length > 2) return;
 
23677                     if (moved.isArea() || unmoved.isArea()) return;
 
23679                     cache.intersection[node.id] = {
 
23682                         unmovedId: unmoved.id,
 
23683                         movedIsEP: isEndpoint(moved, node.id),
 
23684                         unmovedIsEP: isEndpoint(unmoved, node.id)
 
23696             cache.intersection = {};
 
23697             cache.replacedVertex = {};
 
23698             cache.startLoc = {};
 
23702             cacheEntities(moveIds);
 
23703             cacheIntersections(cache.ways);
 
23704             cache.nodes = _.filter(cache.nodes, canMove);
 
23711     // Place a vertex where the moved vertex used to be, to preserve way shape..
 
23712     function replaceMovedVertex(nodeId, wayId, graph, delta) {
 
23713         var way = graph.entity(wayId),
 
23714             moved = graph.entity(nodeId),
 
23715             movedIndex = way.nodes.indexOf(nodeId),
 
23716             len, prevIndex, nextIndex;
 
23718         if (way.isClosed()) {
 
23719             len = way.nodes.length - 1;
 
23720             prevIndex = (movedIndex + len - 1) % len;
 
23721             nextIndex = (movedIndex + len + 1) % len;
 
23723             len = way.nodes.length;
 
23724             prevIndex = movedIndex - 1;
 
23725             nextIndex = movedIndex + 1;
 
23728         var prev = graph.hasEntity(way.nodes[prevIndex]),
 
23729             next = graph.hasEntity(way.nodes[nextIndex]);
 
23731         // Don't add orig vertex at endpoint..
 
23732         if (!prev || !next) return graph;
 
23734         var key = wayId + '_' + nodeId,
 
23735             orig = cache.replacedVertex[key];
 
23738             cache.replacedVertex[key] = orig;
 
23739             cache.startLoc[orig.id] = cache.startLoc[nodeId];
 
23744             start = projection(cache.startLoc[nodeId]);
 
23745             end = projection.invert(vecAdd(start, delta));
 
23747             end = cache.startLoc[nodeId];
 
23749         orig = orig.move(end);
 
23751         var angle = Math.abs(iD.geo.angle(orig, prev, projection) -
 
23752                 iD.geo.angle(orig, next, projection)) * 180 / Math.PI;
 
23754         // Don't add orig vertex if it would just make a straight line..
 
23755         if (angle > 175 && angle < 185) return graph;
 
23757         // Don't add orig vertex if another point is already nearby (within 10m)
 
23758         if (iD.geo.sphericalDistance(prev.loc, orig.loc) < 10 ||
 
23759             iD.geo.sphericalDistance(orig.loc, next.loc) < 10) return graph;
 
23761         // moving forward or backward along way?
 
23762         var p1 = [prev.loc, orig.loc, moved.loc, next.loc].map(projection),
 
23763             p2 = [prev.loc, moved.loc, orig.loc, next.loc].map(projection),
 
23764             d1 = iD.geo.pathLength(p1),
 
23765             d2 = iD.geo.pathLength(p2),
 
23766             insertAt = (d1 < d2) ? movedIndex : nextIndex;
 
23768         // moving around closed loop?
 
23769         if (way.isClosed() && insertAt === 0) insertAt = len;
 
23771         way = way.addNode(orig.id, insertAt);
 
23772         return graph.replace(orig).replace(way);
 
23775     // Reorder nodes around intersections that have moved..
 
23776     function unZorroIntersection(intersection, graph) {
 
23777         var vertex = graph.entity(intersection.nodeId),
 
23778             way1 = graph.entity(intersection.movedId),
 
23779             way2 = graph.entity(intersection.unmovedId),
 
23780             isEP1 = intersection.movedIsEP,
 
23781             isEP2 = intersection.unmovedIsEP;
 
23783         // don't move the vertex if it is the endpoint of both ways.
 
23784         if (isEP1 && isEP2) return graph;
 
23786         var nodes1 = _.without(graph.childNodes(way1), vertex),
 
23787             nodes2 = _.without(graph.childNodes(way2), vertex);
 
23789         if (way1.isClosed() && way1.first() === vertex.id) nodes1.push(nodes1[0]);
 
23790         if (way2.isClosed() && way2.first() === vertex.id) nodes2.push(nodes2[0]);
 
23792         var edge1 = !isEP1 && iD.geo.chooseEdge(nodes1, projection(vertex.loc), projection),
 
23793             edge2 = !isEP2 && iD.geo.chooseEdge(nodes2, projection(vertex.loc), projection),
 
23796         // snap vertex to nearest edge (or some point between them)..
 
23797         if (!isEP1 && !isEP2) {
 
23798             var epsilon = 1e-4, maxIter = 10;
 
23799             for (var i = 0; i < maxIter; i++) {
 
23800                 loc = iD.geo.interp(edge1.loc, edge2.loc, 0.5);
 
23801                 edge1 = iD.geo.chooseEdge(nodes1, projection(loc), projection);
 
23802                 edge2 = iD.geo.chooseEdge(nodes2, projection(loc), projection);
 
23803                 if (Math.abs(edge1.distance - edge2.distance) < epsilon) break;
 
23805         } else if (!isEP1) {
 
23811         graph = graph.replace(vertex.move(loc));
 
23813         // if zorro happened, reorder nodes..
 
23814         if (!isEP1 && edge1.index !== way1.nodes.indexOf(vertex.id)) {
 
23815             way1 = way1.removeNode(vertex.id).addNode(vertex.id, edge1.index);
 
23816             graph = graph.replace(way1);
 
23818         if (!isEP2 && edge2.index !== way2.nodes.indexOf(vertex.id)) {
 
23819             way2 = way2.removeNode(vertex.id).addNode(vertex.id, edge2.index);
 
23820             graph = graph.replace(way2);
 
23827     function cleanupIntersections(graph) {
 
23828         _.each(cache.intersection, function(obj) {
 
23829             graph = replaceMovedVertex(obj.nodeId, obj.movedId, graph, delta);
 
23830             graph = replaceMovedVertex(obj.nodeId, obj.unmovedId, graph, null);
 
23831             graph = unZorroIntersection(obj, graph);
 
23837     // check if moving way endpoint can cross an unmoved way, if so limit delta..
 
23838     function limitDelta(graph) {
 
23839         _.each(cache.intersection, function(obj) {
 
23840             if (!obj.movedIsEP) return;
 
23842             var node = graph.entity(obj.nodeId),
 
23843                 start = projection(node.loc),
 
23844                 end = vecAdd(start, delta),
 
23845                 movedNodes = graph.childNodes(graph.entity(obj.movedId)),
 
23846                 movedPath = _.map(_.map(movedNodes, 'loc'),
 
23847                     function(loc) { return vecAdd(projection(loc), delta); }),
 
23848                 unmovedNodes = graph.childNodes(graph.entity(obj.unmovedId)),
 
23849                 unmovedPath = _.map(_.map(unmovedNodes, 'loc'), projection),
 
23850                 hits = iD.geo.pathIntersections(movedPath, unmovedPath);
 
23852             for (var i = 0; i < hits.length; i++) {
 
23853                 if (_.isEqual(hits[i], end)) continue;
 
23854                 var edge = iD.geo.chooseEdge(unmovedNodes, end, projection);
 
23855                 delta = vecSub(projection(edge.loc), start);
 
23861     var action = function(graph) {
 
23862         if (delta[0] === 0 && delta[1] === 0) return graph;
 
23866         if (!_.isEmpty(cache.intersection)) {
 
23870         _.each(cache.nodes, function(id) {
 
23871             var node = graph.entity(id),
 
23872                 start = projection(node.loc),
 
23873                 end = vecAdd(start, delta);
 
23874             graph = graph.replace(node.move(projection.invert(end)));
 
23877         if (!_.isEmpty(cache.intersection)) {
 
23878             graph = cleanupIntersections(graph);
 
23884     action.disabled = function(graph) {
 
23885         function incompleteRelation(id) {
 
23886             var entity = graph.entity(id);
 
23887             return entity.type === 'relation' && !entity.isComplete(graph);
 
23890         if (_.some(moveIds, incompleteRelation))
 
23891             return 'incomplete_relation';
 
23894     action.delta = function() {
 
23900 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
 
23901 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
 
23902 iD.actions.MoveNode = function(nodeId, loc) {
 
23903     return function(graph) {
 
23904         return graph.replace(graph.entity(nodeId).move(loc));
 
23907 iD.actions.Noop = function() {
 
23908     return function(graph) {
 
23913  * Based on https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/potlatch2/tools/Quadrilateralise.as
 
23916 iD.actions.Orthogonalize = function(wayId, projection) {
 
23917     var threshold = 12, // degrees within right or straight to alter
 
23918         lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180),
 
23919         upperThreshold = Math.cos(threshold * Math.PI / 180);
 
23921     var action = function(graph) {
 
23922         var way = graph.entity(wayId),
 
23923             nodes = graph.childNodes(way),
 
23924             points = _.uniq(nodes).map(function(n) { return projection(n.loc); }),
 
23925             corner = {i: 0, dotp: 1},
 
23927             i, j, score, motions;
 
23929         if (nodes.length === 4) {
 
23930             for (i = 0; i < 1000; i++) {
 
23931                 motions = points.map(calcMotion);
 
23932                 points[corner.i] = addPoints(points[corner.i],motions[corner.i]);
 
23933                 score = corner.dotp;
 
23934                 if (score < epsilon) {
 
23939             graph = graph.replace(graph.entity(nodes[corner.i].id)
 
23940                 .move(projection.invert(points[corner.i])));
 
23943                 originalPoints = _.clone(points);
 
23946             for (i = 0; i < 1000; i++) {
 
23947                 motions = points.map(calcMotion);
 
23948                 for (j = 0; j < motions.length; j++) {
 
23949                     points[j] = addPoints(points[j],motions[j]);
 
23951                 var newScore = squareness(points);
 
23952                 if (newScore < score) {
 
23953                     best = _.clone(points);
 
23956                 if (score < epsilon) {
 
23963             for (i = 0; i < points.length; i++) {
 
23964                 // only move the points that actually moved
 
23965                 if (originalPoints[i][0] !== points[i][0] || originalPoints[i][1] !== points[i][1]) {
 
23966                     graph = graph.replace(graph.entity(nodes[i].id)
 
23967                         .move(projection.invert(points[i])));
 
23971             // remove empty nodes on straight sections
 
23972             for (i = 0; i < points.length; i++) {
 
23973                 var node = nodes[i];
 
23975                 if (graph.parentWays(node).length > 1 ||
 
23976                     graph.parentRelations(node).length ||
 
23977                     node.hasInterestingTags()) {
 
23982                 var dotp = normalizedDotProduct(i, points);
 
23983                 if (dotp < -1 + epsilon) {
 
23984                     graph = iD.actions.DeleteNode(nodes[i].id)(graph);
 
23991         function calcMotion(b, i, array) {
 
23992             var a = array[(i - 1 + array.length) % array.length],
 
23993                 c = array[(i + 1) % array.length],
 
23994                 p = subtractPoints(a, b),
 
23995                 q = subtractPoints(c, b),
 
23998             scale = 2 * Math.min(iD.geo.euclideanDistance(p, [0, 0]), iD.geo.euclideanDistance(q, [0, 0]));
 
23999             p = normalizePoint(p, 1.0);
 
24000             q = normalizePoint(q, 1.0);
 
24002             dotp = filterDotProduct(p[0] * q[0] + p[1] * q[1]);
 
24004             // nasty hack to deal with almost-straight segments (angle is closer to 180 than to 90/270).
 
24005             if (array.length > 3) {
 
24006                 if (dotp < -0.707106781186547) {
 
24009             } else if (dotp && Math.abs(dotp) < corner.dotp) {
 
24011                 corner.dotp = Math.abs(dotp);
 
24014             return normalizePoint(addPoints(p, q), 0.1 * dotp * scale);
 
24018     function squareness(points) {
 
24019         return points.reduce(function(sum, val, i, array) {
 
24020             var dotp = normalizedDotProduct(i, array);
 
24022             dotp = filterDotProduct(dotp);
 
24023             return sum + 2.0 * Math.min(Math.abs(dotp - 1.0), Math.min(Math.abs(dotp), Math.abs(dotp + 1)));
 
24027     function normalizedDotProduct(i, points) {
 
24028         var a = points[(i - 1 + points.length) % points.length],
 
24030             c = points[(i + 1) % points.length],
 
24031             p = subtractPoints(a, b),
 
24032             q = subtractPoints(c, b);
 
24034         p = normalizePoint(p, 1.0);
 
24035         q = normalizePoint(q, 1.0);
 
24037         return p[0] * q[0] + p[1] * q[1];
 
24040     function subtractPoints(a, b) {
 
24041         return [a[0] - b[0], a[1] - b[1]];
 
24044     function addPoints(a, b) {
 
24045         return [a[0] + b[0], a[1] + b[1]];
 
24048     function normalizePoint(point, scale) {
 
24049         var vector = [0, 0];
 
24050         var length = Math.sqrt(point[0] * point[0] + point[1] * point[1]);
 
24051         if (length !== 0) {
 
24052             vector[0] = point[0] / length;
 
24053             vector[1] = point[1] / length;
 
24056         vector[0] *= scale;
 
24057         vector[1] *= scale;
 
24062     function filterDotProduct(dotp) {
 
24063         if (lowerThreshold > Math.abs(dotp) || Math.abs(dotp) > upperThreshold) {
 
24070     action.disabled = function(graph) {
 
24071         var way = graph.entity(wayId),
 
24072             nodes = graph.childNodes(way),
 
24073             points = _.uniq(nodes).map(function(n) { return projection(n.loc); });
 
24075         if (squareness(points)) {
 
24079         return 'not_squarish';
 
24084 // Create a restriction relation for `turn`, which must have the following structure:
 
24087 //         from: { node: <node ID>, way: <way ID> },
 
24088 //         via:  { node: <node ID> },
 
24089 //         to:   { node: <node ID>, way: <way ID> },
 
24090 //         restriction: <'no_right_turn', 'no_left_turn', etc.>
 
24093 // This specifies a restriction of type `restriction` when traveling from
 
24094 // `from.node` in `from.way` toward `to.node` in `to.way` via `via.node`.
 
24095 // (The action does not check that these entities form a valid intersection.)
 
24097 // If `restriction` is not provided, it is automatically determined by
 
24098 // iD.geo.inferRestriction.
 
24100 // If necessary, the `from` and `to` ways are split. In these cases, `from.node`
 
24101 // and `to.node` are used to determine which portion of the split ways become
 
24102 // members of the restriction.
 
24104 // For testing convenience, accepts an ID to assign to the new relation.
 
24105 // Normally, this will be undefined and the relation will automatically
 
24106 // be assigned a new ID.
 
24108 iD.actions.RestrictTurn = function(turn, projection, restrictionId) {
 
24109     return function(graph) {
 
24110         var from = graph.entity(turn.from.way),
 
24111             via  = graph.entity(turn.via.node),
 
24112             to   = graph.entity(turn.to.way);
 
24114         function isClosingNode(way, nodeId) {
 
24115             return nodeId === way.first() && nodeId === way.last();
 
24118         function split(toOrFrom) {
 
24119             var newID = toOrFrom.newID || iD.Way().id;
 
24120             graph = iD.actions.Split(via.id, [newID])
 
24121                 .limitWays([toOrFrom.way])(graph);
 
24123             var a = graph.entity(newID),
 
24124                 b = graph.entity(toOrFrom.way);
 
24126             if (a.nodes.indexOf(toOrFrom.node) !== -1) {
 
24133         if (!from.affix(via.id) || isClosingNode(from, via.id)) {
 
24134             if (turn.from.node === turn.to.node) {
 
24136                 from = to = split(turn.from)[0];
 
24137             } else if (turn.from.way === turn.to.way) {
 
24138                 // Straight-on or circular
 
24139                 var s = split(turn.from);
 
24144                 from = split(turn.from)[0];
 
24148         if (!to.affix(via.id) || isClosingNode(to, via.id)) {
 
24149             to = split(turn.to)[0];
 
24152         return graph.replace(iD.Relation({
 
24155                 type: 'restriction',
 
24156                 restriction: turn.restriction ||
 
24157                     iD.geo.inferRestriction(
 
24165                 {id: from.id, type: 'way',  role: 'from'},
 
24166                 {id: via.id,  type: 'node', role: 'via'},
 
24167                 {id: to.id,   type: 'way',  role: 'to'}
 
24173   Order the nodes of a way in reverse order and reverse any direction dependent tags
 
24174   other than `oneway`. (We assume that correcting a backwards oneway is the primary
 
24175   reason for reversing a way.)
 
24177   The following transforms are performed:
 
24180           *:right=* ⟺ *:left=*
 
24181         *:forward=* ⟺ *:backward=*
 
24182        direction=up ⟺ direction=down
 
24183          incline=up ⟺ incline=down
 
24187        role=forward ⟺ role=backward
 
24188          role=north ⟺ role=south
 
24189           role=east ⟺ role=west
 
24191    In addition, numeric-valued `incline` tags are negated.
 
24193    The JOSM implementation was used as a guide, but transformations that were of unclear benefit
 
24194    or adjusted tags that don't seem to be used in practice were omitted.
 
24197       http://wiki.openstreetmap.org/wiki/Forward_%26_backward,_left_%26_right
 
24198       http://wiki.openstreetmap.org/wiki/Key:direction#Steps
 
24199       http://wiki.openstreetmap.org/wiki/Key:incline
 
24200       http://wiki.openstreetmap.org/wiki/Route#Members
 
24201       http://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java
 
24203 iD.actions.Reverse = function(wayId, options) {
 
24204     var replacements = [
 
24205             [/:right$/, ':left'], [/:left$/, ':right'],
 
24206             [/:forward$/, ':backward'], [/:backward$/, ':forward']
 
24208         numeric = /^([+\-]?)(?=[\d.])/,
 
24210             forward: 'backward',
 
24211             backward: 'forward',
 
24218     function reverseKey(key) {
 
24219         for (var i = 0; i < replacements.length; ++i) {
 
24220             var replacement = replacements[i];
 
24221             if (replacement[0].test(key)) {
 
24222                 return key.replace(replacement[0], replacement[1]);
 
24228     function reverseValue(key, value) {
 
24229         if (key === 'incline' && numeric.test(value)) {
 
24230             return value.replace(numeric, function(_, sign) { return sign === '-' ? '' : '-'; });
 
24231         } else if (key === 'incline' || key === 'direction') {
 
24232             return {up: 'down', down: 'up'}[value] || value;
 
24233         } else if (options && options.reverseOneway && key === 'oneway') {
 
24234             return {yes: '-1', '1': '-1', '-1': 'yes'}[value] || value;
 
24236             return {left: 'right', right: 'left'}[value] || value;
 
24240     return function(graph) {
 
24241         var way = graph.entity(wayId),
 
24242             nodes = way.nodes.slice().reverse(),
 
24243             tags = {}, key, role;
 
24245         for (key in way.tags) {
 
24246             tags[reverseKey(key)] = reverseValue(key, way.tags[key]);
 
24249         graph.parentRelations(way).forEach(function(relation) {
 
24250             relation.members.forEach(function(member, index) {
 
24251                 if (member.id === way.id && (role = roleReversals[member.role])) {
 
24252                     relation = relation.updateMember({role: role}, index);
 
24253                     graph = graph.replace(relation);
 
24258         return graph.replace(way.update({nodes: nodes, tags: tags}));
 
24261 iD.actions.Revert = function(id) {
 
24263     var action = function(graph) {
 
24264         var entity = graph.hasEntity(id),
 
24265             base = graph.base().entities[id];
 
24267         if (entity && !base) {    // entity will be removed..
 
24268             if (entity.type === 'node') {
 
24269                 graph.parentWays(entity)
 
24270                     .forEach(function(parent) {
 
24271                         parent = parent.removeNode(id);
 
24272                         graph = graph.replace(parent);
 
24274                         if (parent.isDegenerate()) {
 
24275                             graph = iD.actions.DeleteWay(parent.id)(graph);
 
24280             graph.parentRelations(entity)
 
24281                 .forEach(function(parent) {
 
24282                     parent = parent.removeMembersWithID(id);
 
24283                     graph = graph.replace(parent);
 
24285                     if (parent.isDegenerate()) {
 
24286                         graph = iD.actions.DeleteRelation(parent.id)(graph);
 
24291         return graph.revert(id);
 
24296 iD.actions.RotateWay = function(wayId, pivot, angle, projection) {
 
24297     return function(graph) {
 
24298         return graph.update(function(graph) {
 
24299             var way = graph.entity(wayId);
 
24301             _.uniq(way.nodes).forEach(function(id) {
 
24303                 var node = graph.entity(id),
 
24304                     point = projection(node.loc),
 
24307                 radial[0] = point[0] - pivot[0];
 
24308                 radial[1] = point[1] - pivot[1];
 
24311                     radial[0] * Math.cos(angle) - radial[1] * Math.sin(angle) + pivot[0],
 
24312                     radial[0] * Math.sin(angle) + radial[1] * Math.cos(angle) + pivot[1]
 
24315                 graph = graph.replace(node.move(projection.invert(point)));
 
24322 // Split a way at the given node.
 
24324 // Optionally, split only the given ways, if multiple ways share
 
24327 // This is the inverse of `iD.actions.Join`.
 
24329 // For testing convenience, accepts an ID to assign to the new way.
 
24330 // Normally, this will be undefined and the way will automatically
 
24331 // be assigned a new ID.
 
24334 //   https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/SplitWayAction.as
 
24336 iD.actions.Split = function(nodeId, newWayIds) {
 
24339     // if the way is closed, we need to search for a partner node
 
24340     // to split the way at.
 
24342     // The following looks for a node that is both far away from
 
24343     // the initial node in terms of way segment length and nearby
 
24344     // in terms of beeline-distance. This assures that areas get
 
24345     // split on the most "natural" points (independent of the number
 
24347     // For example: bone-shaped areas get split across their waist
 
24348     // line, circles across the diameter.
 
24349     function splitArea(nodes, idxA, graph) {
 
24350         var lengths = new Array(nodes.length),
 
24356         function wrap(index) {
 
24357             return iD.util.wrap(index, nodes.length);
 
24360         function dist(nA, nB) {
 
24361             return iD.geo.sphericalDistance(graph.entity(nA).loc, graph.entity(nB).loc);
 
24364         // calculate lengths
 
24366         for (i = wrap(idxA+1); i !== idxA; i = wrap(i+1)) {
 
24367             length += dist(nodes[i], nodes[wrap(i-1)]);
 
24368             lengths[i] = length;
 
24372         for (i = wrap(idxA-1); i !== idxA; i = wrap(i-1)) {
 
24373             length += dist(nodes[i], nodes[wrap(i+1)]);
 
24374             if (length < lengths[i])
 
24375                 lengths[i] = length;
 
24378         // determine best opposite node to split
 
24379         for (i = 0; i < nodes.length; i++) {
 
24380             var cost = lengths[i] / dist(nodes[idxA], nodes[i]);
 
24390     function split(graph, wayA, newWayId) {
 
24391         var wayB = iD.Way({id: newWayId, tags: wayA.tags}),
 
24394             isArea = wayA.isArea(),
 
24395             isOuter = iD.geo.isSimpleMultipolygonOuterMember(wayA, graph);
 
24397         if (wayA.isClosed()) {
 
24398             var nodes = wayA.nodes.slice(0, -1),
 
24399                 idxA = _.indexOf(nodes, nodeId),
 
24400                 idxB = splitArea(nodes, idxA, graph);
 
24403                 nodesA = nodes.slice(idxA).concat(nodes.slice(0, idxB + 1));
 
24404                 nodesB = nodes.slice(idxB, idxA + 1);
 
24406                 nodesA = nodes.slice(idxA, idxB + 1);
 
24407                 nodesB = nodes.slice(idxB).concat(nodes.slice(0, idxA + 1));
 
24410             var idx = _.indexOf(wayA.nodes, nodeId, 1);
 
24411             nodesA = wayA.nodes.slice(0, idx + 1);
 
24412             nodesB = wayA.nodes.slice(idx);
 
24415         wayA = wayA.update({nodes: nodesA});
 
24416         wayB = wayB.update({nodes: nodesB});
 
24418         graph = graph.replace(wayA);
 
24419         graph = graph.replace(wayB);
 
24421         graph.parentRelations(wayA).forEach(function(relation) {
 
24422             if (relation.isRestriction()) {
 
24423                 var via = relation.memberByRole('via');
 
24424                 if (via && wayB.contains(via.id)) {
 
24425                     relation = relation.updateMember({id: wayB.id}, relation.memberById(wayA.id).index);
 
24426                     graph = graph.replace(relation);
 
24429                 if (relation === isOuter) {
 
24430                     graph = graph.replace(relation.mergeTags(wayA.tags));
 
24431                     graph = graph.replace(wayA.update({tags: {}}));
 
24432                     graph = graph.replace(wayB.update({tags: {}}));
 
24438                     role: relation.memberById(wayA.id).role
 
24441                 graph = iD.actions.AddMember(relation.id, member)(graph);
 
24445         if (!isOuter && isArea) {
 
24446             var multipolygon = iD.Relation({
 
24447                 tags: _.extend({}, wayA.tags, {type: 'multipolygon'}),
 
24449                     {id: wayA.id, role: 'outer', type: 'way'},
 
24450                     {id: wayB.id, role: 'outer', type: 'way'}
 
24453             graph = graph.replace(multipolygon);
 
24454             graph = graph.replace(wayA.update({tags: {}}));
 
24455             graph = graph.replace(wayB.update({tags: {}}));
 
24461     var action = function(graph) {
 
24462         var candidates = action.ways(graph);
 
24463         for (var i = 0; i < candidates.length; i++) {
 
24464             graph = split(graph, candidates[i], newWayIds && newWayIds[i]);
 
24469     action.ways = function(graph) {
 
24470         var node = graph.entity(nodeId),
 
24471             parents = graph.parentWays(node),
 
24472             hasLines = _.some(parents, function(parent) { return parent.geometry(graph) === 'line'; });
 
24474         return parents.filter(function(parent) {
 
24475             if (wayIds && wayIds.indexOf(parent.id) === -1)
 
24478             if (!wayIds && hasLines && parent.geometry(graph) !== 'line')
 
24481             if (parent.isClosed()) {
 
24485             for (var i = 1; i < parent.nodes.length - 1; i++) {
 
24486                 if (parent.nodes[i] === nodeId) {
 
24495     action.disabled = function(graph) {
 
24496         var candidates = action.ways(graph);
 
24497         if (candidates.length === 0 || (wayIds && wayIds.length !== candidates.length))
 
24498             return 'not_eligible';
 
24501     action.limitWays = function(_) {
 
24502         if (!arguments.length) return wayIds;
 
24510  * Based on https://github.com/openstreetmap/potlatch2/net/systemeD/potlatch2/tools/Straighten.as
 
24513 iD.actions.Straighten = function(wayId, projection) {
 
24514     function positionAlongWay(n, s, e) {
 
24515         return ((n[0] - s[0]) * (e[0] - s[0]) + (n[1] - s[1]) * (e[1] - s[1]))/
 
24516                 (Math.pow(e[0] - s[0], 2) + Math.pow(e[1] - s[1], 2));
 
24519     var action = function(graph) {
 
24520         var way = graph.entity(wayId),
 
24521             nodes = graph.childNodes(way),
 
24522             points = nodes.map(function(n) { return projection(n.loc); }),
 
24523             startPoint = points[0],
 
24524             endPoint = points[points.length-1],
 
24528         for (i = 1; i < points.length-1; i++) {
 
24529             var node = nodes[i],
 
24532             if (graph.parentWays(node).length > 1 ||
 
24533                 graph.parentRelations(node).length ||
 
24534                 node.hasInterestingTags()) {
 
24536                 var u = positionAlongWay(point, startPoint, endPoint),
 
24537                     p0 = startPoint[0] + u * (endPoint[0] - startPoint[0]),
 
24538                     p1 = startPoint[1] + u * (endPoint[1] - startPoint[1]);
 
24540                 graph = graph.replace(graph.entity(node.id)
 
24541                     .move(projection.invert([p0, p1])));
 
24544                 if (toDelete.indexOf(node) === -1) {
 
24545                     toDelete.push(node);
 
24550         for (i = 0; i < toDelete.length; i++) {
 
24551             graph = iD.actions.DeleteNode(toDelete[i].id)(graph);
 
24557     action.disabled = function(graph) {
 
24558         // check way isn't too bendy
 
24559         var way = graph.entity(wayId),
 
24560             nodes = graph.childNodes(way),
 
24561             points = nodes.map(function(n) { return projection(n.loc); }),
 
24562             startPoint = points[0],
 
24563             endPoint = points[points.length-1],
 
24564             threshold = 0.2 * Math.sqrt(Math.pow(startPoint[0] - endPoint[0], 2) + Math.pow(startPoint[1] - endPoint[1], 2)),
 
24567         if (threshold === 0) {
 
24568             return 'too_bendy';
 
24571         for (i = 1; i < points.length-1; i++) {
 
24572             var point = points[i],
 
24573                 u = positionAlongWay(point, startPoint, endPoint),
 
24574                 p0 = startPoint[0] + u * (endPoint[0] - startPoint[0]),
 
24575                 p1 = startPoint[1] + u * (endPoint[1] - startPoint[1]),
 
24576                 dist = Math.sqrt(Math.pow(p0 - point[0], 2) + Math.pow(p1 - point[1], 2));
 
24578             // to bendy if point is off by 20% of total start/end distance in projected space
 
24579             if (isNaN(dist) || dist > threshold) {
 
24580                 return 'too_bendy';
 
24587 // Remove the effects of `turn.restriction` on `turn`, which must have the
 
24588 // following structure:
 
24591 //         from: { node: <node ID>, way: <way ID> },
 
24592 //         via:  { node: <node ID> },
 
24593 //         to:   { node: <node ID>, way: <way ID> },
 
24594 //         restriction: <relation ID>
 
24597 // In the simple case, `restriction` is a reference to a `no_*` restriction
 
24598 // on the turn itself. In this case, it is simply deleted.
 
24600 // The more complex case is where `restriction` references an `only_*`
 
24601 // restriction on a different turn in the same intersection. In that case,
 
24602 // that restriction is also deleted, but at the same time restrictions on
 
24603 // the turns other than the first two are created.
 
24605 iD.actions.UnrestrictTurn = function(turn) {
 
24606     return function(graph) {
 
24607         return iD.actions.DeleteRelation(turn.restriction)(graph);
 
24611 iD.behavior.AddWay = function(context) {
 
24612     var event = d3.dispatch('start', 'startFromWay', 'startFromNode'),
 
24613         draw = iD.behavior.Draw(context);
 
24615     var addWay = function(surface) {
 
24616         draw.on('click', event.start)
 
24617             .on('clickWay', event.startFromWay)
 
24618             .on('clickNode', event.startFromNode)
 
24619             .on('cancel', addWay.cancel)
 
24620             .on('finish', addWay.cancel);
 
24623             .dblclickEnable(false);
 
24625         surface.call(draw);
 
24628     addWay.off = function(surface) {
 
24629         surface.call(draw.off);
 
24632     addWay.cancel = function() {
 
24633         window.setTimeout(function() {
 
24634             context.map().dblclickEnable(true);
 
24637         context.enter(iD.modes.Browse(context));
 
24640     addWay.tail = function(text) {
 
24645     return d3.rebind(addWay, event, 'on');
 
24647 iD.behavior.Breathe = function() {
 
24648     var duration = 800,
 
24649         selector = '.selected.shadow, .selected .shadow',
 
24650         selected = d3.select(null),
 
24655     function reset(selection) {
 
24657             .style('stroke-opacity', null)
 
24658             .style('stroke-width', null)
 
24659             .style('fill-opacity', null)
 
24663     function setAnimationParams(transition, fromTo) {
 
24665             .style('stroke-opacity', function(d) { return params[d.id][fromTo].opacity; })
 
24666             .style('stroke-width', function(d) { return params[d.id][fromTo].width; })
 
24667             .style('fill-opacity', function(d) { return params[d.id][fromTo].opacity; })
 
24668             .style('r', function(d) { return params[d.id][fromTo].width; });
 
24671     function calcAnimationParams(selection) {
 
24674             .each(function(d) {
 
24675                 var s = d3.select(this),
 
24676                     tag = s.node().tagName,
 
24677                     p = {'from': {}, 'to': {}},
 
24680                 // determine base opacity and width
 
24681                 if (tag === 'circle') {
 
24682                     opacity = parseFloat(s.style('fill-opacity') || 0.5);
 
24683                     width = parseFloat(s.style('r') || 15.5);
 
24685                     opacity = parseFloat(s.style('stroke-opacity') || 0.7);
 
24686                     width = parseFloat(s.style('stroke-width') || 10);
 
24689                 // calculate from/to interpolation params..
 
24691                 p.from.opacity = opacity * 0.6;
 
24692                 p.to.opacity = opacity * 1.25;
 
24693                 p.from.width = width * 0.9;
 
24694                 p.to.width = width * (tag === 'circle' ? 1.5 : 1.25);
 
24699     function run(surface, fromTo) {
 
24700         var toFrom = (fromTo === 'from' ? 'to': 'from'),
 
24701             currSelected = surface.selectAll(selector),
 
24702             currClassed = surface.attr('class'),
 
24705         if (done || currSelected.empty()) {
 
24706             selected.call(reset);
 
24710         if (!_.isEqual(currSelected, selected) || currClassed !== classed) {
 
24711             selected.call(reset);
 
24712             classed = currClassed;
 
24713             selected = currSelected.call(calcAnimationParams);
 
24718             .call(setAnimationParams, fromTo)
 
24719             .duration(duration)
 
24720             .each(function() { ++n; })
 
24721             .each('end', function() {
 
24722                 if (!--n) {  // call once
 
24723                     surface.call(run, toFrom);
 
24728     var breathe = function(surface) {
 
24730         d3.timer(function() {
 
24731             if (done) return true;
 
24733             var currSelected = surface.selectAll(selector);
 
24734             if (currSelected.empty()) return false;
 
24736             surface.call(run, 'from');
 
24741     breathe.off = function() {
 
24752 iD.behavior.Copy = function(context) {
 
24753     var keybinding = d3.keybinding('copy');
 
24755     function groupEntities(ids, graph) {
 
24756         var entities = ids.map(function (id) { return graph.entity(id); });
 
24757         return _.extend({relation: [], way: [], node: []},
 
24758             _.groupBy(entities, function(entity) { return entity.type; }));
 
24761     function getDescendants(id, graph, descendants) {
 
24762         var entity = graph.entity(id),
 
24765         descendants = descendants || {};
 
24767         if (entity.type === 'relation') {
 
24768             children = _.map(entity.members, 'id');
 
24769         } else if (entity.type === 'way') {
 
24770             children = entity.nodes;
 
24775         for (i = 0; i < children.length; i++) {
 
24776             if (!descendants[children[i]]) {
 
24777                 descendants[children[i]] = true;
 
24778                 descendants = getDescendants(children[i], graph, descendants);
 
24782         return descendants;
 
24785     function doCopy() {
 
24786         d3.event.preventDefault();
 
24787         if (context.inIntro()) return;
 
24789         var graph = context.graph(),
 
24790             selected = groupEntities(context.selectedIDs(), graph),
 
24795         for (i = 0; i < selected.relation.length; i++) {
 
24796             entity = selected.relation[i];
 
24797             if (!skip[entity.id] && entity.isComplete(graph)) {
 
24798                 canCopy.push(entity.id);
 
24799                 skip = getDescendants(entity.id, graph, skip);
 
24802         for (i = 0; i < selected.way.length; i++) {
 
24803             entity = selected.way[i];
 
24804             if (!skip[entity.id]) {
 
24805                 canCopy.push(entity.id);
 
24806                 skip = getDescendants(entity.id, graph, skip);
 
24809         for (i = 0; i < selected.node.length; i++) {
 
24810             entity = selected.node[i];
 
24811             if (!skip[entity.id]) {
 
24812                 canCopy.push(entity.id);
 
24816         context.copyIDs(canCopy);
 
24820         keybinding.on(iD.ui.cmd('⌘C'), doCopy);
 
24821         d3.select(document).call(keybinding);
 
24825     copy.off = function() {
 
24826         d3.select(document).call(keybinding.off);
 
24832     `iD.behavior.drag` is like `d3.behavior.drag`, with the following differences:
 
24834     * The `origin` function is expected to return an [x, y] tuple rather than an
 
24836     * The events are `start`, `move`, and `end`.
 
24837       (https://github.com/mbostock/d3/issues/563)
 
24838     * The `start` event is not dispatched until the first cursor movement occurs.
 
24839       (https://github.com/mbostock/d3/pull/368)
 
24840     * The `move` event has a `point` and `delta` [x, y] tuple properties rather
 
24841       than `x`, `y`, `dx`, and `dy` properties.
 
24842     * The `end` event is not dispatched if no movement occurs.
 
24843     * An `off` function is available that unbinds the drag's internal event handlers.
 
24844     * Delegation is supported via the `delegate` function.
 
24847 iD.behavior.drag = function() {
 
24848     function d3_eventCancel() {
 
24849       d3.event.stopPropagation();
 
24850       d3.event.preventDefault();
 
24853     var event = d3.dispatch('start', 'move', 'end'),
 
24857         event_, target, surface;
 
24859     event.of = function(thiz, argumentz) {
 
24860       return function(e1) {
 
24861         var e0 = e1.sourceEvent = d3.event;
 
24865           event[e1.type].apply(thiz, argumentz);
 
24872     var d3_event_userSelectProperty = iD.util.prefixCSSProperty('UserSelect'),
 
24873         d3_event_userSelectSuppress = d3_event_userSelectProperty ?
 
24875                 var selection = d3.selection(),
 
24876                     select = selection.style(d3_event_userSelectProperty);
 
24877                 selection.style(d3_event_userSelectProperty, 'none');
 
24878                 return function () {
 
24879                     selection.style(d3_event_userSelectProperty, select);
 
24883                 var w = d3.select(window).on('selectstart.' + type, d3_eventCancel);
 
24884                 return function () {
 
24885                     w.on('selectstart.' + type, null);
 
24889     function mousedown() {
 
24891         event_ = event.of(target, arguments);
 
24892         var eventTarget = d3.event.target,
 
24893             touchId = d3.event.touches ? d3.event.changedTouches[0].identifier : null,
 
24897             selectEnable = d3_event_userSelectSuppress(touchId !== null ? 'drag-' + touchId : 'drag');
 
24899         var w = d3.select(window)
 
24900             .on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', dragmove)
 
24901             .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', dragend, true);
 
24904             offset = origin.apply(target, arguments);
 
24905             offset = [offset[0] - origin_[0], offset[1] - origin_[1]];
 
24910         if (touchId === null) d3.event.stopPropagation();
 
24913             var p = target.parentNode || surface;
 
24914             return touchId !== null ? d3.touches(p).filter(function(p) {
 
24915                 return p.identifier === touchId;
 
24916             })[0] : d3.mouse(p);
 
24919         function dragmove() {
 
24922                 dx = p[0] - origin_[0],
 
24923                 dy = p[1] - origin_[1];
 
24925             if (dx === 0 && dy === 0)
 
24940                 point: [p[0] + offset[0],  p[1] + offset[1]],
 
24945         function dragend() {
 
24952                 if (d3.event.target === eventTarget) w.on('click.drag', click, true);
 
24955             w.on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', null)
 
24956                 .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', null);
 
24962             w.on('click.drag', null);
 
24966     function drag(selection) {
 
24967         var matchesSelector = iD.util.prefixDOMProperty('matchesSelector'),
 
24968             delegate = mousedown;
 
24971             delegate = function() {
 
24973                     target = d3.event.target;
 
24974                 for (; target && target !== root; target = target.parentNode) {
 
24975                     if (target[matchesSelector](selector) &&
 
24976                             (!filter || filter(target.__data__))) {
 
24977                         return mousedown.call(target, target.__data__);
 
24983         selection.on('mousedown.drag' + selector, delegate)
 
24984             .on('touchstart.drag' + selector, delegate);
 
24987     drag.off = function(selection) {
 
24988         selection.on('mousedown.drag' + selector, null)
 
24989             .on('touchstart.drag' + selector, null);
 
24992     drag.delegate = function(_) {
 
24993         if (!arguments.length) return selector;
 
24998     drag.filter = function(_) {
 
24999         if (!arguments.length) return origin;
 
25004     drag.origin = function (_) {
 
25005         if (!arguments.length) return origin;
 
25010     drag.cancel = function() {
 
25012             .on('mousemove.drag', null)
 
25013             .on('mouseup.drag', null);
 
25017     drag.target = function() {
 
25018         if (!arguments.length) return target;
 
25019         target = arguments[0];
 
25020         event_ = event.of(target, Array.prototype.slice.call(arguments, 1));
 
25024     drag.surface = function() {
 
25025         if (!arguments.length) return surface;
 
25026         surface = arguments[0];
 
25030     return d3.rebind(drag, event, 'on');
 
25032 iD.behavior.Draw = function(context) {
 
25033     var event = d3.dispatch('move', 'click', 'clickWay',
 
25034             'clickNode', 'undo', 'cancel', 'finish'),
 
25035         keybinding = d3.keybinding('draw'),
 
25036         hover = iD.behavior.Hover(context)
 
25038             .on('hover', context.ui().sidebar.hover),
 
25039         tail = iD.behavior.Tail(),
 
25040         edit = iD.behavior.Edit(context),
 
25041         closeTolerance = 4,
 
25043         mouseLeave = false,
 
25045         cached = iD.behavior.Draw;
 
25048         if (d3.event.altKey) return {};
 
25050         if (d3.event.type === 'keydown') {
 
25051             return (lastMouse && lastMouse.target.__data__) || {};
 
25053             return d3.event.target.__data__ || {};
 
25057     function mousedown() {
 
25060             var p = context.container().node();
 
25061             return touchId !== null ? d3.touches(p).filter(function(p) {
 
25062                 return p.identifier === touchId;
 
25063             })[0] : d3.mouse(p);
 
25066         var element = d3.select(this),
 
25067             touchId = d3.event.touches ? d3.event.changedTouches[0].identifier : null,
 
25071         element.on('mousemove.draw', null);
 
25073         d3.select(window).on('mouseup.draw', function() {
 
25074             var t2 = +new Date(),
 
25076                 dist = iD.geo.euclideanDistance(p1, p2);
 
25078             element.on('mousemove.draw', mousemove);
 
25079             d3.select(window).on('mouseup.draw', null);
 
25081             if (dist < closeTolerance || (dist < tolerance && (t2 - t1) < 500)) {
 
25082                 // Prevent a quick second click
 
25083                 d3.select(window).on('click.draw-block', function() {
 
25084                     d3.event.stopPropagation();
 
25087                 context.map().dblclickEnable(false);
 
25089                 window.setTimeout(function() {
 
25090                     context.map().dblclickEnable(true);
 
25091                     d3.select(window).on('click.draw-block', null);
 
25099     function mousemove() {
 
25100         lastMouse = d3.event;
 
25101         event.move(datum());
 
25104     function mouseenter() {
 
25105         mouseLeave = false;
 
25108     function mouseleave() {
 
25114         if (d.type === 'way') {
 
25115             var dims = context.map().dimensions(),
 
25116                 mouse = context.mouse(),
 
25118                 trySnap = mouse[0] > pad && mouse[0] < dims[0] - pad &&
 
25119                     mouse[1] > pad && mouse[1] < dims[1] - pad;
 
25122                 var choice = iD.geo.chooseEdge(context.childNodes(d), context.mouse(), context.projection),
 
25123                     edge = [d.nodes[choice.index - 1], d.nodes[choice.index]];
 
25124                 event.clickWay(choice.loc, edge);
 
25126                 event.click(context.map().mouseCoordinates());
 
25129         } else if (d.type === 'node') {
 
25130             event.clickNode(d);
 
25133             event.click(context.map().mouseCoordinates());
 
25138         var currSpace = context.mouse();
 
25139         if (cached.disableSpace && cached.lastSpace) {
 
25140             var dist = iD.geo.euclideanDistance(cached.lastSpace, currSpace);
 
25141             if (dist > tolerance) {
 
25142                 cached.disableSpace = false;
 
25146         if (cached.disableSpace || mouseLeave || !lastMouse) return;
 
25148         // user must move mouse or release space bar to allow another click
 
25149         cached.lastSpace = currSpace;
 
25150         cached.disableSpace = true;
 
25152         d3.select(window).on('keyup.space-block', function() {
 
25153             cached.disableSpace = false;
 
25154             d3.select(window).on('keyup.space-block', null);
 
25157         d3.event.preventDefault();
 
25161     function backspace() {
 
25162         d3.event.preventDefault();
 
25167         d3.event.preventDefault();
 
25172         d3.event.preventDefault();
 
25176     function draw(selection) {
 
25177         context.install(hover);
 
25178         context.install(edit);
 
25180         if (!context.inIntro() && !cached.usedTails[tail.text()]) {
 
25181             context.install(tail);
 
25185             .on('⌫', backspace)
 
25189             .on('space', space)
 
25190             .on('⌥space', space);
 
25193             .on('mouseenter.draw', mouseenter)
 
25194             .on('mouseleave.draw', mouseleave)
 
25195             .on('mousedown.draw', mousedown)
 
25196             .on('mousemove.draw', mousemove);
 
25198         d3.select(document)
 
25204     draw.off = function(selection) {
 
25205         context.ui().sidebar.hover.cancel();
 
25206         context.uninstall(hover);
 
25207         context.uninstall(edit);
 
25209         if (!context.inIntro() && !cached.usedTails[tail.text()]) {
 
25210             context.uninstall(tail);
 
25211             cached.usedTails[tail.text()] = true;
 
25215             .on('mouseenter.draw', null)
 
25216             .on('mouseleave.draw', null)
 
25217             .on('mousedown.draw', null)
 
25218             .on('mousemove.draw', null);
 
25221             .on('mouseup.draw', null);
 
25222             // note: keyup.space-block, click.draw-block should remain
 
25224         d3.select(document)
 
25225             .call(keybinding.off);
 
25228     draw.tail = function(_) {
 
25233     return d3.rebind(draw, event, 'on');
 
25236 iD.behavior.Draw.usedTails = {};
 
25237 iD.behavior.Draw.disableSpace = false;
 
25238 iD.behavior.Draw.lastSpace = null;
 
25239 iD.behavior.DrawWay = function(context, wayId, index, mode, baseGraph) {
 
25240     var way = context.entity(wayId),
 
25241         isArea = context.geometry(wayId) === 'area',
 
25243         annotation = t((way.isDegenerate() ?
 
25244             'operations.start.annotation.' :
 
25245             'operations.continue.annotation.') + context.geometry(wayId)),
 
25246         draw = iD.behavior.Draw(context);
 
25248     var startIndex = typeof index === 'undefined' ? way.nodes.length - 1 : 0,
 
25249         start = iD.Node({loc: context.graph().entity(way.nodes[startIndex]).loc}),
 
25250         end = iD.Node({loc: context.map().mouseCoordinates()}),
 
25252             nodes: typeof index === 'undefined' ? [start.id, end.id] : [end.id, start.id],
 
25253             tags: _.clone(way.tags)
 
25256     var f = context[way.isDegenerate() ? 'replace' : 'perform'];
 
25258         f(iD.actions.AddEntity(end),
 
25259             iD.actions.AddVertex(wayId, end.id, index));
 
25261         f(iD.actions.AddEntity(start),
 
25262             iD.actions.AddEntity(end),
 
25263             iD.actions.AddEntity(segment));
 
25266     function move(datum) {
 
25269         if (datum.type === 'node' && datum.id !== end.id) {
 
25272         } else if (datum.type === 'way' && datum.id !== segment.id) {
 
25273             var dims = context.map().dimensions(),
 
25274                 mouse = context.mouse(),
 
25276                 trySnap = mouse[0] > pad && mouse[0] < dims[0] - pad &&
 
25277                     mouse[1] > pad && mouse[1] < dims[1] - pad;
 
25280                 loc = iD.geo.chooseEdge(context.childNodes(datum), context.mouse(), context.projection).loc;
 
25285             loc = context.map().mouseCoordinates();
 
25288         context.replace(iD.actions.MoveNode(end.id, loc));
 
25291     function undone() {
 
25293         context.enter(iD.modes.Browse(context));
 
25296     function setActiveElements() {
 
25297         var active = isArea ? [wayId, end.id] : [segment.id, start.id, end.id];
 
25298         context.surface().selectAll(iD.util.entitySelector(active))
 
25299             .classed('active', true);
 
25302     var drawWay = function(surface) {
 
25303         draw.on('move', move)
 
25304             .on('click', drawWay.add)
 
25305             .on('clickWay', drawWay.addWay)
 
25306             .on('clickNode', drawWay.addNode)
 
25307             .on('undo', context.undo)
 
25308             .on('cancel', drawWay.cancel)
 
25309             .on('finish', drawWay.finish);
 
25312             .dblclickEnable(false)
 
25313             .on('drawn.draw', setActiveElements);
 
25315         setActiveElements();
 
25317         surface.call(draw);
 
25320             .on('undone.draw', undone);
 
25323     drawWay.off = function(surface) {
 
25328             .on('drawn.draw', null);
 
25330         surface.call(draw.off)
 
25331             .selectAll('.active')
 
25332             .classed('active', false);
 
25335             .on('undone.draw', null);
 
25338     function ReplaceTemporaryNode(newNode) {
 
25339         return function(graph) {
 
25342                     .replace(way.addNode(newNode.id, index))
 
25347                     .replace(graph.entity(wayId).addNode(newNode.id, index))
 
25355     // Accept the current position of the temporary node and continue drawing.
 
25356     drawWay.add = function(loc) {
 
25358         // prevent duplicate nodes
 
25359         var last = context.hasEntity(way.nodes[way.nodes.length - (isArea ? 2 : 1)]);
 
25360         if (last && last.loc[0] === loc[0] && last.loc[1] === loc[1]) return;
 
25362         var newNode = iD.Node({loc: loc});
 
25365             iD.actions.AddEntity(newNode),
 
25366             ReplaceTemporaryNode(newNode),
 
25370         context.enter(mode);
 
25373     // Connect the way to an existing way.
 
25374     drawWay.addWay = function(loc, edge) {
 
25375         var previousEdge = startIndex ?
 
25376             [way.nodes[startIndex], way.nodes[startIndex - 1]] :
 
25377             [way.nodes[0], way.nodes[1]];
 
25379         // Avoid creating duplicate segments
 
25380         if (!isArea && iD.geo.edgeEqual(edge, previousEdge))
 
25383         var newNode = iD.Node({ loc: loc });
 
25386             iD.actions.AddMidpoint({ loc: loc, edge: edge}, newNode),
 
25387             ReplaceTemporaryNode(newNode),
 
25391         context.enter(mode);
 
25394     // Connect the way to an existing node and continue drawing.
 
25395     drawWay.addNode = function(node) {
 
25397         // Avoid creating duplicate segments
 
25398         if (way.areAdjacent(node.id, way.nodes[way.nodes.length - 1])) return;
 
25401             ReplaceTemporaryNode(node),
 
25405         context.enter(mode);
 
25408     // Finish the draw operation, removing the temporary node. If the way has enough
 
25409     // nodes to be valid, it's selected. Otherwise, return to browse mode.
 
25410     drawWay.finish = function() {
 
25414         window.setTimeout(function() {
 
25415             context.map().dblclickEnable(true);
 
25418         if (context.hasEntity(wayId)) {
 
25420                 iD.modes.Select(context, [wayId])
 
25421                     .suppressMenu(true)
 
25422                     .newFeature(true));
 
25424             context.enter(iD.modes.Browse(context));
 
25428     // Cancel the draw operation and return to browse, deleting everything drawn.
 
25429     drawWay.cancel = function() {
 
25431             d3.functor(baseGraph),
 
25432             t('operations.cancel_draw.annotation'));
 
25434         window.setTimeout(function() {
 
25435             context.map().dblclickEnable(true);
 
25439         context.enter(iD.modes.Browse(context));
 
25442     drawWay.tail = function(text) {
 
25449 iD.behavior.Edit = function(context) {
 
25452             .minzoom(context.minEditableZoom());
 
25455     edit.off = function() {
 
25462 iD.behavior.Hash = function(context) {
 
25463     var s0 = null, // cached location.hash
 
25464         lat = 90 - 1e-8; // allowable latitude range
 
25466     var parser = function(map, s) {
 
25467         var q = iD.util.stringQs(s);
 
25468         var args = (q.map || '').split('/').map(Number);
 
25469         if (args.length < 3 || args.some(isNaN)) {
 
25470             return true; // replace bogus hash
 
25471         } else if (s !== formatter(map).slice(1)) {
 
25472             map.centerZoom([args[1],
 
25473                 Math.min(lat, Math.max(-lat, args[2]))], args[0]);
 
25477     var formatter = function(map) {
 
25478         var mode = context.mode(),
 
25479             center = map.center(),
 
25481             precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2)),
 
25482             q = _.omit(iD.util.stringQs(location.hash.substring(1)), 'comment'),
 
25485         if (mode && mode.id === 'browse') {
 
25488             var selected = context.selectedIDs().filter(function(id) {
 
25489                 return !context.entity(id).isNew();
 
25491             if (selected.length) {
 
25492                 newParams.id = selected.join(',');
 
25496         newParams.map = zoom.toFixed(2) +
 
25497                 '/' + center[0].toFixed(precision) +
 
25498                 '/' + center[1].toFixed(precision);
 
25500         return '#' + iD.util.qsString(_.assign(q, newParams), true);
 
25503     function update() {
 
25504         if (context.inIntro()) return;
 
25505         var s1 = formatter(context.map());
 
25506         if (s0 !== s1) location.replace(s0 = s1); // don't recenter the map!
 
25509     var throttledUpdate = _.throttle(update, 500);
 
25511     function hashchange() {
 
25512         if (location.hash === s0) return; // ignore spurious hashchange events
 
25513         if (parser(context.map(), (s0 = location.hash).substring(1))) {
 
25514             update(); // replace bogus hash
 
25520             .on('move.hash', throttledUpdate);
 
25523             .on('enter.hash', throttledUpdate);
 
25526             .on('hashchange.hash', hashchange);
 
25528         if (location.hash) {
 
25529             var q = iD.util.stringQs(location.hash.substring(1));
 
25530             if (q.id) context.zoomToEntity(q.id.split(',')[0], !q.map);
 
25531             if (q.comment) context.storage('comment', q.comment);
 
25533             if (q.map) hash.hadHash = true;
 
25537     hash.off = function() {
 
25538         throttledUpdate.cancel();
 
25541             .on('move.hash', null);
 
25544             .on('enter.hash', null);
 
25547             .on('hashchange.hash', null);
 
25549         location.hash = '';
 
25555    The hover behavior adds the `.hover` class on mouseover to all elements to which
 
25556    the identical datum is bound, and removes it on mouseout.
 
25558    The :hover pseudo-class is insufficient for iD's purposes because a datum's visual
 
25559    representation may consist of several elements scattered throughout the DOM hierarchy.
 
25560    Only one of these elements can have the :hover pseudo-class, but all of them will
 
25561    have the .hover class.
 
25563 iD.behavior.Hover = function() {
 
25564     var dispatch = d3.dispatch('hover'),
 
25569     function keydown() {
 
25570         if (altDisables && d3.event.keyCode === d3.keybinding.modifierCodes.alt) {
 
25571             dispatch.hover(null);
 
25572             selection.selectAll('.hover')
 
25573                 .classed('hover-suppressed', true)
 
25574                 .classed('hover', false);
 
25579         if (altDisables && d3.event.keyCode === d3.keybinding.modifierCodes.alt) {
 
25580             dispatch.hover(target ? target.id : null);
 
25581             selection.selectAll('.hover-suppressed')
 
25582                 .classed('hover-suppressed', false)
 
25583                 .classed('hover', true);
 
25587     var hover = function(__) {
 
25590         function enter(d) {
 
25591             if (d === target) return;
 
25595             selection.selectAll('.hover')
 
25596                 .classed('hover', false);
 
25597             selection.selectAll('.hover-suppressed')
 
25598                 .classed('hover-suppressed', false);
 
25600             if (target instanceof iD.Entity) {
 
25601                 var selector = '.' + target.id;
 
25603                 if (target.type === 'relation') {
 
25604                     target.members.forEach(function(member) {
 
25605                         selector += ', .' + member.id;
 
25609                 var suppressed = altDisables && d3.event && d3.event.altKey;
 
25611                 selection.selectAll(selector)
 
25612                     .classed(suppressed ? 'hover-suppressed' : 'hover', true);
 
25614                 dispatch.hover(target.id);
 
25616                 dispatch.hover(null);
 
25622         function mouseover() {
 
25624             var target = d3.event.target;
 
25625             enter(target ? target.__data__ : null);
 
25628         function mouseout() {
 
25630             var target = d3.event.relatedTarget;
 
25631             enter(target ? target.__data__ : null);
 
25634         function mousedown() {
 
25637                 .on('mouseup.hover', mouseup);
 
25640         function mouseup() {
 
25645             .on('mouseover.hover', mouseover)
 
25646             .on('mouseout.hover', mouseout)
 
25647             .on('mousedown.hover', mousedown)
 
25648             .on('mouseup.hover', mouseup);
 
25651             .on('keydown.hover', keydown)
 
25652             .on('keyup.hover', keyup);
 
25655     hover.off = function(selection) {
 
25656         selection.selectAll('.hover')
 
25657             .classed('hover', false);
 
25658         selection.selectAll('.hover-suppressed')
 
25659             .classed('hover-suppressed', false);
 
25662             .on('mouseover.hover', null)
 
25663             .on('mouseout.hover', null)
 
25664             .on('mousedown.hover', null)
 
25665             .on('mouseup.hover', null);
 
25668             .on('keydown.hover', null)
 
25669             .on('keyup.hover', null)
 
25670             .on('mouseup.hover', null);
 
25673     hover.altDisables = function(_) {
 
25674         if (!arguments.length) return altDisables;
 
25679     return d3.rebind(hover, dispatch, 'on');
 
25681 iD.behavior.Lasso = function(context) {
 
25683     var behavior = function(selection) {
 
25686         function mousedown() {
 
25687             var button = 0;  // left
 
25688             if (d3.event.button === button && d3.event.shiftKey === true) {
 
25692                     .on('mousemove.lasso', mousemove)
 
25693                     .on('mouseup.lasso', mouseup);
 
25695                 d3.event.stopPropagation();
 
25699         function mousemove() {
 
25701                 lasso = iD.ui.Lasso(context);
 
25702                 context.surface().call(lasso);
 
25705             lasso.p(context.mouse());
 
25708         function normalize(a, b) {
 
25710                 [Math.min(a[0], b[0]), Math.min(a[1], b[1])],
 
25711                 [Math.max(a[0], b[0]), Math.max(a[1], b[1])]];
 
25714         function lassoed() {
 
25715             if (!lasso) return [];
 
25717             var graph = context.graph(),
 
25718                 bounds = lasso.extent().map(context.projection.invert),
 
25719                 extent = iD.geo.Extent(normalize(bounds[0], bounds[1]));
 
25721             return _.map(context.intersects(extent).filter(function(entity) {
 
25722                 return entity.type === 'node' &&
 
25723                     iD.geo.pointInPolygon(context.projection(entity.loc), lasso.coordinates) &&
 
25724                     !context.features().isHidden(entity, graph, entity.geometry(graph));
 
25728         function mouseup() {
 
25730                 .on('mousemove.lasso', null)
 
25731                 .on('mouseup.lasso', null);
 
25733             if (!lasso) return;
 
25735             var ids = lassoed();
 
25739                 context.enter(iD.modes.Select(context, ids));
 
25744             .on('mousedown.lasso', mousedown);
 
25747     behavior.off = function(selection) {
 
25748         selection.on('mousedown.lasso', null);
 
25753 iD.behavior.Paste = function(context) {
 
25754     var keybinding = d3.keybinding('paste');
 
25756     function omitTag(v, k) {
 
25764             k === 'description' ||
 
25765             k.indexOf('name') !== -1 ||
 
25766             k.indexOf('wiki') === 0 ||
 
25767             k.indexOf('addr:') === 0 ||
 
25768             k.indexOf('contact:') === 0
 
25772     function doPaste() {
 
25773         d3.event.preventDefault();
 
25774         if (context.inIntro()) return;
 
25776         var baseGraph = context.graph(),
 
25777             mouse = context.mouse(),
 
25778             projection = context.projection,
 
25779             viewport = iD.geo.Extent(projection.clipExtent()).polygon();
 
25781         if (!iD.geo.pointInPolygon(mouse, viewport)) return;
 
25783         var extent = iD.geo.Extent(),
 
25784             oldIDs = context.copyIDs(),
 
25785             oldGraph = context.copyGraph(),
 
25788         if (!oldIDs.length) return;
 
25790         var action = iD.actions.CopyEntities(oldIDs, oldGraph);
 
25791         context.perform(action);
 
25793         var copies = action.copies();
 
25794         for (var id in copies) {
 
25795             var oldEntity = oldGraph.entity(id),
 
25796                 newEntity = copies[id];
 
25798             extent._extend(oldEntity.extent(oldGraph));
 
25799             newIDs.push(newEntity.id);
 
25800             context.perform(iD.actions.ChangeTags(newEntity.id, _.omit(newEntity.tags, omitTag)));
 
25803         // Put pasted objects where mouse pointer is..
 
25804         var center = projection(extent.center()),
 
25805             delta = [ mouse[0] - center[0], mouse[1] - center[1] ];
 
25807         context.perform(iD.actions.Move(newIDs, delta, projection));
 
25808         context.enter(iD.modes.Move(context, newIDs, baseGraph));
 
25812         keybinding.on(iD.ui.cmd('⌘V'), doPaste);
 
25813         d3.select(document).call(keybinding);
 
25817     paste.off = function() {
 
25818         d3.select(document).call(keybinding.off);
 
25823 iD.behavior.Select = function(context) {
 
25824     function keydown() {
 
25825         if (d3.event && d3.event.shiftKey) {
 
25827                 .classed('behavior-multiselect', true);
 
25832         if (!d3.event || !d3.event.shiftKey) {
 
25834                 .classed('behavior-multiselect', false);
 
25839         var datum = d3.event.target.__data__,
 
25840             lasso = d3.select('#surface .lasso').node(),
 
25841             mode = context.mode();
 
25843         if (!(datum instanceof iD.Entity)) {
 
25844             if (!d3.event.shiftKey && !lasso && mode.id !== 'browse')
 
25845                 context.enter(iD.modes.Browse(context));
 
25847         } else if (!d3.event.shiftKey && !lasso) {
 
25848             // Avoid re-entering Select mode with same entity.
 
25849             if (context.selectedIDs().length !== 1 || context.selectedIDs()[0] !== datum.id) {
 
25850                 context.enter(iD.modes.Select(context, [datum.id]));
 
25852                 mode.suppressMenu(false).reselect();
 
25854         } else if (context.selectedIDs().indexOf(datum.id) >= 0) {
 
25855             var selectedIDs = _.without(context.selectedIDs(), datum.id);
 
25856             context.enter(selectedIDs.length ?
 
25857                 iD.modes.Select(context, selectedIDs) :
 
25858                 iD.modes.Browse(context));
 
25861             context.enter(iD.modes.Select(context, context.selectedIDs().concat([datum.id])));
 
25865     var behavior = function(selection) {
 
25867             .on('keydown.select', keydown)
 
25868             .on('keyup.select', keyup);
 
25870         selection.on('click.select', click);
 
25875     behavior.off = function(selection) {
 
25877             .on('keydown.select', null)
 
25878             .on('keyup.select', null);
 
25880         selection.on('click.select', null);
 
25887 iD.behavior.Tail = function() {
 
25891         tooltipSize = [0, 0],
 
25892         selectionSize = [0, 0];
 
25894     function tail(selection) {
 
25898             .on('resize.tail', function() { selectionSize = selection.dimensions(); });
 
25901             container.style('display', 'block');
 
25902             tooltipSize = container.dimensions();
 
25905         function mousemove() {
 
25906             if (container.style('display') === 'none') show();
 
25907             var xoffset = ((d3.event.clientX + tooltipSize[0] + xmargin) > selectionSize[0]) ?
 
25908                 -tooltipSize[0] - xmargin : xmargin;
 
25909             container.classed('left', xoffset > 0);
 
25910             iD.util.setTransform(container, d3.event.clientX + xoffset, d3.event.clientY);
 
25913         function mouseleave() {
 
25914             if (d3.event.relatedTarget !== container.node()) {
 
25915                 container.style('display', 'none');
 
25919         function mouseenter() {
 
25920             if (d3.event.relatedTarget !== container.node()) {
 
25925         container = d3.select(document.body)
 
25927             .style('display', 'none')
 
25928             .attr('class', 'tail tooltip-inner');
 
25930         container.append('div')
 
25934             .on('mousemove.tail', mousemove)
 
25935             .on('mouseenter.tail', mouseenter)
 
25936             .on('mouseleave.tail', mouseleave);
 
25939             .on('mousemove.tail', mousemove);
 
25941         tooltipSize = container.dimensions();
 
25942         selectionSize = selection.dimensions();
 
25945     tail.off = function(selection) {
 
25949             .on('mousemove.tail', null)
 
25953             .on('mousemove.tail', null)
 
25954             .on('mouseenter.tail', null)
 
25955             .on('mouseleave.tail', null);
 
25958             .on('resize.tail', null);
 
25961     tail.text = function(_) {
 
25962         if (!arguments.length) return text;
 
25970 iD.modes.AddArea = function(context) {
 
25974         title: t('modes.add_area.title'),
 
25975         description: t('modes.add_area.description'),
 
25979     var behavior = iD.behavior.AddWay(context)
 
25980             .tail(t('modes.add_area.tail'))
 
25981             .on('start', start)
 
25982             .on('startFromWay', startFromWay)
 
25983             .on('startFromNode', startFromNode),
 
25984         defaultTags = {area: 'yes'};
 
25986     function start(loc) {
 
25987         var graph = context.graph(),
 
25988             node = iD.Node({loc: loc}),
 
25989             way = iD.Way({tags: defaultTags});
 
25992             iD.actions.AddEntity(node),
 
25993             iD.actions.AddEntity(way),
 
25994             iD.actions.AddVertex(way.id, node.id),
 
25995             iD.actions.AddVertex(way.id, node.id));
 
25997         context.enter(iD.modes.DrawArea(context, way.id, graph));
 
26000     function startFromWay(loc, edge) {
 
26001         var graph = context.graph(),
 
26002             node = iD.Node({loc: loc}),
 
26003             way = iD.Way({tags: defaultTags});
 
26006             iD.actions.AddEntity(node),
 
26007             iD.actions.AddEntity(way),
 
26008             iD.actions.AddVertex(way.id, node.id),
 
26009             iD.actions.AddVertex(way.id, node.id),
 
26010             iD.actions.AddMidpoint({ loc: loc, edge: edge }, node));
 
26012         context.enter(iD.modes.DrawArea(context, way.id, graph));
 
26015     function startFromNode(node) {
 
26016         var graph = context.graph(),
 
26017             way = iD.Way({tags: defaultTags});
 
26020             iD.actions.AddEntity(way),
 
26021             iD.actions.AddVertex(way.id, node.id),
 
26022             iD.actions.AddVertex(way.id, node.id));
 
26024         context.enter(iD.modes.DrawArea(context, way.id, graph));
 
26027     mode.enter = function() {
 
26028         context.install(behavior);
 
26031     mode.exit = function() {
 
26032         context.uninstall(behavior);
 
26037 iD.modes.AddLine = function(context) {
 
26041         title: t('modes.add_line.title'),
 
26042         description: t('modes.add_line.description'),
 
26046     var behavior = iD.behavior.AddWay(context)
 
26047         .tail(t('modes.add_line.tail'))
 
26048         .on('start', start)
 
26049         .on('startFromWay', startFromWay)
 
26050         .on('startFromNode', startFromNode);
 
26052     function start(loc) {
 
26053         var baseGraph = context.graph(),
 
26054             node = iD.Node({loc: loc}),
 
26058             iD.actions.AddEntity(node),
 
26059             iD.actions.AddEntity(way),
 
26060             iD.actions.AddVertex(way.id, node.id));
 
26062         context.enter(iD.modes.DrawLine(context, way.id, baseGraph));
 
26065     function startFromWay(loc, edge) {
 
26066         var baseGraph = context.graph(),
 
26067             node = iD.Node({loc: loc}),
 
26071             iD.actions.AddEntity(node),
 
26072             iD.actions.AddEntity(way),
 
26073             iD.actions.AddVertex(way.id, node.id),
 
26074             iD.actions.AddMidpoint({ loc: loc, edge: edge }, node));
 
26076         context.enter(iD.modes.DrawLine(context, way.id, baseGraph));
 
26079     function startFromNode(node) {
 
26080         var baseGraph = context.graph(),
 
26084             iD.actions.AddEntity(way),
 
26085             iD.actions.AddVertex(way.id, node.id));
 
26087         context.enter(iD.modes.DrawLine(context, way.id, baseGraph));
 
26090     mode.enter = function() {
 
26091         context.install(behavior);
 
26094     mode.exit = function() {
 
26095         context.uninstall(behavior);
 
26100 iD.modes.AddPoint = function(context) {
 
26104         title: t('modes.add_point.title'),
 
26105         description: t('modes.add_point.description'),
 
26109     var behavior = iD.behavior.Draw(context)
 
26110         .tail(t('modes.add_point.tail'))
 
26112         .on('clickWay', addWay)
 
26113         .on('clickNode', addNode)
 
26114         .on('cancel', cancel)
 
26115         .on('finish', cancel);
 
26117     function add(loc) {
 
26118         var node = iD.Node({loc: loc});
 
26121             iD.actions.AddEntity(node),
 
26122             t('operations.add.annotation.point'));
 
26125             iD.modes.Select(context, [node.id])
 
26126                 .suppressMenu(true)
 
26127                 .newFeature(true));
 
26130     function addWay(loc) {
 
26134     function addNode(node) {
 
26138     function cancel() {
 
26139         context.enter(iD.modes.Browse(context));
 
26142     mode.enter = function() {
 
26143         context.install(behavior);
 
26146     mode.exit = function() {
 
26147         context.uninstall(behavior);
 
26152 iD.modes.Browse = function(context) {
 
26156         title: t('modes.browse.title'),
 
26157         description: t('modes.browse.description')
 
26161         iD.behavior.Paste(context),
 
26162         iD.behavior.Hover(context)
 
26163             .on('hover', context.ui().sidebar.hover),
 
26164         iD.behavior.Select(context),
 
26165         iD.behavior.Lasso(context),
 
26166         iD.modes.DragNode(context).behavior];
 
26168     mode.enter = function() {
 
26169         behaviors.forEach(function(behavior) {
 
26170             context.install(behavior);
 
26173         // Get focus on the body.
 
26174         if (document.activeElement && document.activeElement.blur) {
 
26175             document.activeElement.blur();
 
26179             context.ui().sidebar.show(sidebar);
 
26181             context.ui().sidebar.select(null);
 
26185     mode.exit = function() {
 
26186         context.ui().sidebar.hover.cancel();
 
26187         behaviors.forEach(function(behavior) {
 
26188             context.uninstall(behavior);
 
26192             context.ui().sidebar.hide();
 
26196     mode.sidebar = function(_) {
 
26197         if (!arguments.length) return sidebar;
 
26204 iD.modes.DragNode = function(context) {
 
26215         hover = iD.behavior.Hover(context)
 
26217             .on('hover', context.ui().sidebar.hover),
 
26218         edit = iD.behavior.Edit(context);
 
26220     function edge(point, size) {
 
26221         var pad = [30, 100, 30, 100];
 
26222         if (point[0] > size[0] - pad[0]) return [-10, 0];
 
26223         else if (point[0] < pad[2]) return [10, 0];
 
26224         else if (point[1] > size[1] - pad[1]) return [0, -10];
 
26225         else if (point[1] < pad[3]) return [0, 10];
 
26229     function startNudge(nudge) {
 
26230         if (nudgeInterval) window.clearInterval(nudgeInterval);
 
26231         nudgeInterval = window.setInterval(function() {
 
26232             context.pan(nudge);
 
26236     function stopNudge() {
 
26237         if (nudgeInterval) window.clearInterval(nudgeInterval);
 
26238         nudgeInterval = null;
 
26241     function moveAnnotation(entity) {
 
26242         return t('operations.move.annotation.' + entity.geometry(context.graph()));
 
26245     function connectAnnotation(entity) {
 
26246         return t('operations.connect.annotation.' + entity.geometry(context.graph()));
 
26249     function origin(entity) {
 
26250         return context.projection(entity.loc);
 
26253     function start(entity) {
 
26254         cancelled = d3.event.sourceEvent.shiftKey ||
 
26255             context.features().hasHiddenConnections(entity, context.graph());
 
26257         if (cancelled) return behavior.cancel();
 
26259         wasMidpoint = entity.type === 'midpoint';
 
26261             var midpoint = entity;
 
26262             entity = iD.Node();
 
26263             context.perform(iD.actions.AddMidpoint(midpoint, entity));
 
26265              var vertex = context.surface()
 
26266                 .selectAll('.' + entity.id);
 
26267              behavior.target(vertex.node(), entity);
 
26271                 iD.actions.Noop());
 
26274         activeIDs = _.map(context.graph().parentWays(entity), 'id');
 
26275         activeIDs.push(entity.id);
 
26277         context.enter(mode);
 
26281         if (d3.event.sourceEvent.altKey) {
 
26285         return d3.event.sourceEvent.target.__data__ || {};
 
26288     // via https://gist.github.com/shawnbot/4166283
 
26289     function childOf(p, c) {
 
26290         if (p === c) return false;
 
26291         while (c && c !== p) c = c.parentNode;
 
26295     function move(entity) {
 
26296         if (cancelled) return;
 
26297         d3.event.sourceEvent.stopPropagation();
 
26299         var nudge = childOf(context.container().node(),
 
26300             d3.event.sourceEvent.toElement) &&
 
26301             edge(d3.event.point, context.map().dimensions());
 
26303         if (nudge) startNudge(nudge);
 
26306         var loc = context.projection.invert(d3.event.point);
 
26309         if (d.type === 'node' && d.id !== entity.id) {
 
26311         } else if (d.type === 'way' && !d3.select(d3.event.sourceEvent.target).classed('fill')) {
 
26312             loc = iD.geo.chooseEdge(context.childNodes(d), context.mouse(), context.projection).loc;
 
26316             iD.actions.MoveNode(entity.id, loc),
 
26317             moveAnnotation(entity));
 
26320     function end(entity) {
 
26321         if (cancelled) return;
 
26325         if (d.type === 'way') {
 
26326             var choice = iD.geo.chooseEdge(context.childNodes(d), context.mouse(), context.projection);
 
26328                 iD.actions.AddMidpoint({ loc: choice.loc, edge: [d.nodes[choice.index - 1], d.nodes[choice.index]] }, entity),
 
26329                 connectAnnotation(d));
 
26331         } else if (d.type === 'node' && d.id !== entity.id) {
 
26333                 iD.actions.Connect([d.id, entity.id]),
 
26334                 connectAnnotation(d));
 
26336         } else if (wasMidpoint) {
 
26339                 t('operations.add.annotation.vertex'));
 
26344                 moveAnnotation(entity));
 
26347         var reselection = selectedIDs.filter(function(id) {
 
26348             return context.graph().hasEntity(id);
 
26351         if (reselection.length) {
 
26353                 iD.modes.Select(context, reselection)
 
26354                     .suppressMenu(true));
 
26356             context.enter(iD.modes.Browse(context));
 
26360     function cancel() {
 
26362         context.enter(iD.modes.Browse(context));
 
26365     function setActiveElements() {
 
26366         context.surface().selectAll(iD.util.entitySelector(activeIDs))
 
26367             .classed('active', true);
 
26370     var behavior = iD.behavior.drag()
 
26371         .delegate('g.node, g.point, g.midpoint')
 
26372         .surface(context.surface().node())
 
26374         .on('start', start)
 
26378     mode.enter = function() {
 
26379         context.install(hover);
 
26380         context.install(edit);
 
26383             .on('undone.drag-node', cancel);
 
26386             .on('drawn.drag-node', setActiveElements);
 
26388         setActiveElements();
 
26391     mode.exit = function() {
 
26392         context.ui().sidebar.hover.cancel();
 
26393         context.uninstall(hover);
 
26394         context.uninstall(edit);
 
26397             .on('undone.drag-node', null);
 
26400             .on('drawn.drag-node', null);
 
26403             .selectAll('.active')
 
26404             .classed('active', false);
 
26409     mode.selectedIDs = function(_) {
 
26410         if (!arguments.length) return selectedIDs;
 
26415     mode.behavior = behavior;
 
26419 iD.modes.DrawArea = function(context, wayId, baseGraph) {
 
26427     mode.enter = function() {
 
26428         var way = context.entity(wayId),
 
26429             headId = way.nodes[way.nodes.length - 2],
 
26430             tailId = way.first();
 
26432         behavior = iD.behavior.DrawWay(context, wayId, -1, mode, baseGraph)
 
26433             .tail(t('modes.draw_area.tail'));
 
26435         var addNode = behavior.addNode;
 
26437         behavior.addNode = function(node) {
 
26438             if (node.id === headId || node.id === tailId) {
 
26445         context.install(behavior);
 
26448     mode.exit = function() {
 
26449         context.uninstall(behavior);
 
26452     mode.selectedIDs = function() {
 
26458 iD.modes.DrawLine = function(context, wayId, baseGraph, affix) {
 
26466     mode.enter = function() {
 
26467         var way = context.entity(wayId),
 
26468             index = (affix === 'prefix') ? 0 : undefined,
 
26469             headId = (affix === 'prefix') ? way.first() : way.last();
 
26471         behavior = iD.behavior.DrawWay(context, wayId, index, mode, baseGraph)
 
26472             .tail(t('modes.draw_line.tail'));
 
26474         var addNode = behavior.addNode;
 
26476         behavior.addNode = function(node) {
 
26477             if (node.id === headId) {
 
26484         context.install(behavior);
 
26487     mode.exit = function() {
 
26488         context.uninstall(behavior);
 
26491     mode.selectedIDs = function() {
 
26497 iD.modes.Move = function(context, entityIDs, baseGraph) {
 
26503     var keybinding = d3.keybinding('move'),
 
26504         edit = iD.behavior.Edit(context),
 
26505         annotation = entityIDs.length === 1 ?
 
26506             t('operations.move.annotation.' + context.geometry(entityIDs[0])) :
 
26507             t('operations.move.annotation.multiple'),
 
26512     function vecSub(a, b) { return [a[0] - b[0], a[1] - b[1]]; }
 
26514     function edge(point, size) {
 
26515         var pad = [30, 100, 30, 100];
 
26516         if (point[0] > size[0] - pad[0]) return [-10, 0];
 
26517         else if (point[0] < pad[2]) return [10, 0];
 
26518         else if (point[1] > size[1] - pad[1]) return [0, -10];
 
26519         else if (point[1] < pad[3]) return [0, 10];
 
26523     function startNudge(nudge) {
 
26524         if (nudgeInterval) window.clearInterval(nudgeInterval);
 
26525         nudgeInterval = window.setInterval(function() {
 
26526             context.pan(nudge);
 
26528             var currMouse = context.mouse(),
 
26529                 origMouse = context.projection(origin),
 
26530                 delta = vecSub(vecSub(currMouse, origMouse), nudge),
 
26531                 action = iD.actions.Move(entityIDs, delta, context.projection, cache);
 
26533             context.overwrite(action, annotation);
 
26538     function stopNudge() {
 
26539         if (nudgeInterval) window.clearInterval(nudgeInterval);
 
26540         nudgeInterval = null;
 
26544         var currMouse = context.mouse(),
 
26545             origMouse = context.projection(origin),
 
26546             delta = vecSub(currMouse, origMouse),
 
26547             action = iD.actions.Move(entityIDs, delta, context.projection, cache);
 
26549         context.overwrite(action, annotation);
 
26551         var nudge = edge(currMouse, context.map().dimensions());
 
26552         if (nudge) startNudge(nudge);
 
26556     function finish() {
 
26557         d3.event.stopPropagation();
 
26558         context.enter(iD.modes.Select(context, entityIDs).suppressMenu(true));
 
26562     function cancel() {
 
26564             while (context.graph() !== baseGraph) context.pop();
 
26565             context.enter(iD.modes.Browse(context));
 
26568             context.enter(iD.modes.Select(context, entityIDs).suppressMenu(true));
 
26573     function undone() {
 
26574         context.enter(iD.modes.Browse(context));
 
26577     mode.enter = function() {
 
26578         origin = context.map().mouseCoordinates();
 
26581         context.install(edit);
 
26588             .on('mousemove.move', move)
 
26589             .on('click.move', finish);
 
26592             .on('undone.move', undone);
 
26598         d3.select(document)
 
26602     mode.exit = function() {
 
26605         context.uninstall(edit);
 
26608             .on('mousemove.move', null)
 
26609             .on('click.move', null);
 
26612             .on('undone.move', null);
 
26619 iD.modes.RotateWay = function(context, wayId) {
 
26625     var keybinding = d3.keybinding('rotate-way'),
 
26626         edit = iD.behavior.Edit(context);
 
26628     mode.enter = function() {
 
26629         context.install(edit);
 
26631         var annotation = t('operations.rotate.annotation.' + context.geometry(wayId)),
 
26632             way = context.graph().entity(wayId),
 
26633             nodes = _.uniq(context.graph().childNodes(way)),
 
26634             points = nodes.map(function(n) { return context.projection(n.loc); }),
 
26635             pivot = d3.geom.polygon(points).centroid(),
 
26642         function rotate() {
 
26644             var mousePoint = context.mouse(),
 
26645                 newAngle = Math.atan2(mousePoint[1] - pivot[1], mousePoint[0] - pivot[0]);
 
26647             if (typeof angle === 'undefined') angle = newAngle;
 
26650                 iD.actions.RotateWay(wayId, pivot, newAngle - angle, context.projection),
 
26656         function finish() {
 
26657             d3.event.stopPropagation();
 
26658             context.enter(iD.modes.Select(context, [wayId])
 
26659                 .suppressMenu(true));
 
26662         function cancel() {
 
26664             context.enter(iD.modes.Select(context, [wayId])
 
26665                 .suppressMenu(true));
 
26668         function undone() {
 
26669             context.enter(iD.modes.Browse(context));
 
26673             .on('mousemove.rotate-way', rotate)
 
26674             .on('click.rotate-way', finish);
 
26677             .on('undone.rotate-way', undone);
 
26683         d3.select(document)
 
26687     mode.exit = function() {
 
26688         context.uninstall(edit);
 
26691             .on('mousemove.rotate-way', null)
 
26692             .on('click.rotate-way', null);
 
26695             .on('undone.rotate-way', null);
 
26702 iD.modes.Save = function(context) {
 
26703     var ui = iD.ui.Commit(context)
 
26704             .on('cancel', cancel)
 
26707     function cancel() {
 
26708         context.enter(iD.modes.Browse(context));
 
26711     function save(e, tryAgain) {
 
26712         function withChildNodes(ids, graph) {
 
26713             return _.uniq(_.reduce(ids, function(result, id) {
 
26714                 var e = graph.entity(id);
 
26715                 if (e.type === 'way') {
 
26717                         var cn = graph.childNodes(e);
 
26718                         result.push.apply(result, _.map(_.filter(cn, 'version'), 'id'));
 
26720                         /* eslint-disable no-console */
 
26721                         if (typeof console !== 'undefined') console.error(err);
 
26722                         /* eslint-enable no-console */
 
26729         var loading = iD.ui.Loading(context).message(t('save.uploading')).blocking(true),
 
26730             history = context.history(),
 
26731             origChanges = history.changes(iD.actions.DiscardTags(history.difference())),
 
26732             localGraph = context.graph(),
 
26733             remoteGraph = iD.Graph(history.base(), true),
 
26734             modified = _.filter(history.difference().summary(), {changeType: 'modified'}),
 
26735             toCheck = _.map(_.map(modified, 'entity'), 'id'),
 
26736             toLoad = withChildNodes(toCheck, localGraph),
 
26740         if (!tryAgain) history.perform(iD.actions.Noop());  // checkpoint
 
26741         context.container().call(loading);
 
26743         if (toCheck.length) {
 
26744             context.connection().loadMultiple(toLoad, loaded);
 
26750         // Reload modified entities into an alternate graph and check for conflicts..
 
26751         function loaded(err, result) {
 
26752             if (errors.length) return;
 
26756                     msg: err.responseText,
 
26757                     details: [ t('save.status_code', { code: err.status }) ]
 
26763                 _.each(result.data, function(entity) {
 
26764                     remoteGraph.replace(entity);
 
26765                     toLoad = _.without(toLoad, entity.id);
 
26767                     // Because loadMultiple doesn't download /full like loadEntity,
 
26768                     // need to also load children that aren't already being checked..
 
26769                     if (!entity.visible) return;
 
26770                     if (entity.type === 'way') {
 
26771                         loadMore.push.apply(loadMore,
 
26772                             _.difference(entity.nodes, toCheck, toLoad, loadMore));
 
26773                     } else if (entity.type === 'relation' && entity.isMultipolygon()) {
 
26774                         loadMore.push.apply(loadMore,
 
26775                             _.difference(_.map(entity.members, 'id'), toCheck, toLoad, loadMore));
 
26779                 if (loadMore.length) {
 
26780                     toLoad.push.apply(toLoad, loadMore);
 
26781                     context.connection().loadMultiple(loadMore, loaded);
 
26784                 if (!toLoad.length) {
 
26791         function checkConflicts() {
 
26792             function choice(id, text, action) {
 
26793                 return { id: id, text: text, action: function() { history.replace(action); } };
 
26795             function formatUser(d) {
 
26796                 return '<a href="' + context.connection().userURL(d) + '" target="_blank">' + d + '</a>';
 
26798             function entityName(entity) {
 
26799                 return iD.util.displayName(entity) || (iD.util.displayType(entity.id) + ' ' + entity.id);
 
26802             function compareVersions(local, remote) {
 
26803                 if (local.version !== remote.version) return false;
 
26805                 if (local.type === 'way') {
 
26806                     var children = _.union(local.nodes, remote.nodes);
 
26808                     for (var i = 0; i < children.length; i++) {
 
26809                         var a = localGraph.hasEntity(children[i]),
 
26810                             b = remoteGraph.hasEntity(children[i]);
 
26812                         if (a && b && a.version !== b.version) return false;
 
26819             _.each(toCheck, function(id) {
 
26820                 var local = localGraph.entity(id),
 
26821                     remote = remoteGraph.entity(id);
 
26823                 if (compareVersions(local, remote)) return;
 
26825                 var action = iD.actions.MergeRemoteChanges,
 
26826                     merge = action(id, localGraph, remoteGraph, formatUser);
 
26828                 history.replace(merge);
 
26830                 var mergeConflicts = merge.conflicts();
 
26831                 if (!mergeConflicts.length) return;  // merged safely
 
26833                 var forceLocal = action(id, localGraph, remoteGraph).withOption('force_local'),
 
26834                     forceRemote = action(id, localGraph, remoteGraph).withOption('force_remote'),
 
26835                     keepMine = t('save.conflict.' + (remote.visible ? 'keep_local' : 'restore')),
 
26836                     keepTheirs = t('save.conflict.' + (remote.visible ? 'keep_remote' : 'delete'));
 
26840                     name: entityName(local),
 
26841                     details: mergeConflicts,
 
26844                         choice(id, keepMine, forceLocal),
 
26845                         choice(id, keepTheirs, forceRemote)
 
26854         function finalize() {
 
26855             if (conflicts.length) {
 
26856                 conflicts.sort(function(a,b) { return b.id.localeCompare(a.id); });
 
26858             } else if (errors.length) {
 
26861                 var changes = history.changes(iD.actions.DiscardTags(history.difference()));
 
26862                 if (changes.modified.length || changes.created.length || changes.deleted.length) {
 
26863                     context.connection().putChangeset(
 
26866                         history.imageryUsed(),
 
26867                         function(err, changeset_id) {
 
26870                                     msg: err.responseText,
 
26871                                     details: [ t('save.status_code', { code: err.status }) ]
 
26875                                 history.clearSaved();
 
26876                                 success(e, changeset_id);
 
26877                                 // Add delay to allow for postgres replication #1646 #2678
 
26878                                 window.setTimeout(function() {
 
26884                 } else {        // changes were insignificant or reverted by user
 
26893         function showConflicts() {
 
26894             var selection = context.container()
 
26895                 .select('#sidebar')
 
26897                 .attr('class','sidebar-component');
 
26901             selection.call(iD.ui.Conflicts(context)
 
26903                 .on('download', function() {
 
26904                     var data = JXON.stringify(context.connection().osmChangeJXON('CHANGEME', origChanges)),
 
26905                         win = window.open('data:text/xml,' + encodeURIComponent(data), '_blank');
 
26908                 .on('cancel', function() {
 
26910                     selection.remove();
 
26912                 .on('save', function() {
 
26913                     for (var i = 0; i < conflicts.length; i++) {
 
26914                         if (conflicts[i].chosen === 1) {  // user chose "keep theirs"
 
26915                             var entity = context.hasEntity(conflicts[i].id);
 
26916                             if (entity && entity.type === 'way') {
 
26917                                 var children = _.uniq(entity.nodes);
 
26918                                 for (var j = 0; j < children.length; j++) {
 
26919                                     history.replace(iD.actions.Revert(children[j]));
 
26922                             history.replace(iD.actions.Revert(conflicts[i].id));
 
26926                     selection.remove();
 
26933         function showErrors() {
 
26934             var selection = iD.ui.confirm(context.container());
 
26940                 .select('.modal-section.header')
 
26942                 .text(t('save.error'));
 
26944             addErrors(selection, errors);
 
26945             selection.okButton();
 
26949         function addErrors(selection, data) {
 
26950             var message = selection
 
26951                 .select('.modal-section.message-text');
 
26953             var items = message
 
26954                 .selectAll('.error-container')
 
26957             var enter = items.enter()
 
26959                 .attr('class', 'error-container');
 
26963                 .attr('class', 'error-description')
 
26965                 .classed('hide-toggle', true)
 
26966                 .text(function(d) { return d.msg || t('save.unknown_error_details'); })
 
26967                 .on('click', function() {
 
26968                     var error = d3.select(this),
 
26969                         detail = d3.select(this.nextElementSibling),
 
26970                         exp = error.classed('expanded');
 
26972                     detail.style('display', exp ? 'none' : 'block');
 
26973                     error.classed('expanded', !exp);
 
26975                     d3.event.preventDefault();
 
26978             var details = enter
 
26980                 .attr('class', 'error-detail-container')
 
26981                 .style('display', 'none');
 
26985                 .attr('class', 'error-detail-list')
 
26987                 .data(function(d) { return d.details || []; })
 
26990                 .attr('class', 'error-detail-item')
 
26991                 .text(function(d) { return d; });
 
27000     function success(e, changeset_id) {
 
27001         context.enter(iD.modes.Browse(context)
 
27002             .sidebar(iD.ui.Success(context)
 
27007                 .on('cancel', function() {
 
27008                     context.ui().sidebar.hide();
 
27016     mode.enter = function() {
 
27017         context.connection().authenticate(function(err) {
 
27021                 context.ui().sidebar.show(ui);
 
27026     mode.exit = function() {
 
27027         context.ui().sidebar.hide();
 
27032 iD.modes.Select = function(context, selectedIDs) {
 
27038     var keybinding = d3.keybinding('select'),
 
27041             iD.behavior.Copy(context),
 
27042             iD.behavior.Paste(context),
 
27043             iD.behavior.Breathe(context),
 
27044             iD.behavior.Hover(context),
 
27045             iD.behavior.Select(context),
 
27046             iD.behavior.Lasso(context),
 
27047             iD.modes.DragNode(context)
 
27048                 .selectedIDs(selectedIDs)
 
27052         newFeature = false,
 
27053         suppressMenu = false;
 
27055     var wrap = context.container()
 
27056         .select('.inspector-wrap');
 
27059     function singular() {
 
27060         if (selectedIDs.length === 1) {
 
27061             return context.hasEntity(selectedIDs[0]);
 
27065     function closeMenu() {
 
27067             context.surface().call(radialMenu.close);
 
27071     function positionMenu() {
 
27072         if (suppressMenu || !radialMenu) { return; }
 
27074         var entity = singular();
 
27075         if (entity && context.geometry(entity.id) === 'relation') {
 
27076             suppressMenu = true;
 
27077         } else if (entity && entity.type === 'node') {
 
27078             radialMenu.center(context.projection(entity.loc));
 
27080             var point = context.mouse(),
 
27081                 viewport = iD.geo.Extent(context.projection.clipExtent()).polygon();
 
27082             if (iD.geo.pointInPolygon(point, viewport)) {
 
27083                 radialMenu.center(point);
 
27085                 suppressMenu = true;
 
27090     function showMenu() {
 
27092         if (!suppressMenu && radialMenu) {
 
27093             context.surface().call(radialMenu);
 
27097     function toggleMenu() {
 
27098         if (d3.select('.radial-menu').empty()) {
 
27105     mode.selectedIDs = function() {
 
27106         return selectedIDs;
 
27109     mode.reselect = function() {
 
27110         var surfaceNode = context.surface().node();
 
27111         if (surfaceNode.focus) { // FF doesn't support it
 
27112             surfaceNode.focus();
 
27119     mode.newFeature = function(_) {
 
27120         if (!arguments.length) return newFeature;
 
27125     mode.suppressMenu = function(_) {
 
27126         if (!arguments.length) return suppressMenu;
 
27131     mode.enter = function() {
 
27132         function update() {
 
27134             if (_.some(selectedIDs, function(id) { return !context.hasEntity(id); })) {
 
27135                 // Exit mode if selected entity gets undone
 
27136                 context.enter(iD.modes.Browse(context));
 
27140         function dblclick() {
 
27141             var target = d3.select(d3.event.target),
 
27142                 datum = target.datum();
 
27144             if (datum instanceof iD.Way && !target.classed('fill')) {
 
27145                 var choice = iD.geo.chooseEdge(context.childNodes(datum), context.mouse(), context.projection),
 
27148                 var prev = datum.nodes[choice.index - 1],
 
27149                     next = datum.nodes[choice.index];
 
27152                     iD.actions.AddMidpoint({loc: choice.loc, edge: [prev, next]}, node),
 
27153                     t('operations.add.annotation.vertex'));
 
27155                 d3.event.preventDefault();
 
27156                 d3.event.stopPropagation();
 
27160         function selectElements(drawn) {
 
27161             var entity = singular();
 
27162             if (entity && context.geometry(entity.id) === 'relation') {
 
27163                 suppressMenu = true;
 
27167             var selection = context.surface()
 
27168                     .selectAll(iD.util.entityOrMemberSelector(selectedIDs, context.graph()));
 
27170             if (selection.empty()) {
 
27171                 if (drawn) {  // Exit mode if selected DOM elements have disappeared..
 
27172                     context.enter(iD.modes.Browse(context));
 
27176                     .classed('selected', true);
 
27181             if (!context.inIntro()) {
 
27182                 context.enter(iD.modes.Browse(context));
 
27187         behaviors.forEach(function(behavior) {
 
27188             context.install(behavior);
 
27191         var operations = _.without(d3.values(iD.operations), iD.operations.Delete)
 
27192                 .map(function(o) { return o(selectedIDs, context); })
 
27193                 .filter(function(o) { return o.available(); });
 
27195         operations.unshift(iD.operations.Delete(selectedIDs, context));
 
27198             .on('⎋', esc, true)
 
27199             .on('space', toggleMenu);
 
27201         operations.forEach(function(operation) {
 
27202             operation.keys.forEach(function(key) {
 
27203                 keybinding.on(key, function() {
 
27204                     if (!(context.inIntro() || operation.disabled())) {
 
27211         d3.select(document)
 
27214         radialMenu = iD.ui.RadialMenu(context, operations);
 
27216         context.ui().sidebar
 
27217             .select(singular() ? singular().id : null, newFeature);
 
27220             .on('undone.select', update)
 
27221             .on('redone.select', update);
 
27224             .on('move.select', closeMenu)
 
27225             .on('drawn.select', selectElements);
 
27229         var show = d3.event && !suppressMenu;
 
27235         timeout = window.setTimeout(function() {
 
27241                 .on('dblclick.select', dblclick);
 
27244         if (selectedIDs.length > 1) {
 
27245             var entities = iD.ui.SelectionList(context, selectedIDs);
 
27246             context.ui().sidebar.show(entities);
 
27250     mode.exit = function() {
 
27251         if (timeout) window.clearTimeout(timeout);
 
27253         if (inspector) wrap.call(inspector.close);
 
27255         behaviors.forEach(function(behavior) {
 
27256             context.uninstall(behavior);
 
27261         radialMenu = undefined;
 
27264             .on('undone.select', null)
 
27265             .on('redone.select', null);
 
27268             .on('dblclick.select', null)
 
27269             .selectAll('.selected')
 
27270             .classed('selected', false);
 
27272         context.map().on('drawn.select', null);
 
27273         context.ui().sidebar.hide();
 
27278 iD.operations = {};
 
27279 iD.operations.Circularize = function(selectedIDs, context) {
 
27280     var entityId = selectedIDs[0],
 
27281         entity = context.entity(entityId),
 
27282         extent = entity.extent(context.graph()),
 
27283         geometry = context.geometry(entityId),
 
27284         action = iD.actions.Circularize(entityId, context.projection);
 
27286     var operation = function() {
 
27287         var annotation = t('operations.circularize.annotation.' + geometry);
 
27288         context.perform(action, annotation);
 
27291     operation.available = function() {
 
27292         return selectedIDs.length === 1 &&
 
27293             entity.type === 'way' &&
 
27294             _.uniq(entity.nodes).length > 1;
 
27297     operation.disabled = function() {
 
27299         if (extent.percentContainedIn(context.extent()) < 0.8) {
 
27300             reason = 'too_large';
 
27301         } else if (context.hasHiddenConnections(entityId)) {
 
27302             reason = 'connected_to_hidden';
 
27304         return action.disabled(context.graph()) || reason;
 
27307     operation.tooltip = function() {
 
27308         var disable = operation.disabled();
 
27310             t('operations.circularize.' + disable) :
 
27311             t('operations.circularize.description.' + geometry);
 
27314     operation.id = 'circularize';
 
27315     operation.keys = [t('operations.circularize.key')];
 
27316     operation.title = t('operations.circularize.title');
 
27320 iD.operations.Continue = function(selectedIDs, context) {
 
27321     var graph = context.graph(),
 
27322         entities = selectedIDs.map(function(id) { return graph.entity(id); }),
 
27323         geometries = _.extend({line: [], vertex: []},
 
27324             _.groupBy(entities, function(entity) { return entity.geometry(graph); })),
 
27325         vertex = geometries.vertex[0];
 
27327     function candidateWays() {
 
27328         return graph.parentWays(vertex).filter(function(parent) {
 
27329             return parent.geometry(graph) === 'line' &&
 
27330                 parent.affix(vertex.id) &&
 
27331                 (geometries.line.length === 0 || geometries.line[0] === parent);
 
27335     var operation = function() {
 
27336         var candidate = candidateWays()[0];
 
27337         context.enter(iD.modes.DrawLine(
 
27341             candidate.affix(vertex.id)));
 
27344     operation.available = function() {
 
27345         return geometries.vertex.length === 1 && geometries.line.length <= 1 &&
 
27346             !context.features().hasHiddenConnections(vertex, context.graph());
 
27349     operation.disabled = function() {
 
27350         var candidates = candidateWays();
 
27351         if (candidates.length === 0)
 
27352             return 'not_eligible';
 
27353         if (candidates.length > 1)
 
27357     operation.tooltip = function() {
 
27358         var disable = operation.disabled();
 
27360             t('operations.continue.' + disable) :
 
27361             t('operations.continue.description');
 
27364     operation.id = 'continue';
 
27365     operation.keys = [t('operations.continue.key')];
 
27366     operation.title = t('operations.continue.title');
 
27370 iD.operations.Delete = function(selectedIDs, context) {
 
27371     var action = iD.actions.DeleteMultiple(selectedIDs);
 
27373     var operation = function() {
 
27377         if (selectedIDs.length > 1) {
 
27378             annotation = t('operations.delete.annotation.multiple', {n: selectedIDs.length});
 
27381             var id = selectedIDs[0],
 
27382                 entity = context.entity(id),
 
27383                 geometry = context.geometry(id),
 
27384                 parents = context.graph().parentWays(entity),
 
27385                 parent = parents[0];
 
27387             annotation = t('operations.delete.annotation.' + geometry);
 
27389             // Select the next closest node in the way.
 
27390             if (geometry === 'vertex' && parents.length === 1 && parent.nodes.length > 2) {
 
27391                 var nodes = parent.nodes,
 
27392                     i = nodes.indexOf(id);
 
27396                 } else if (i === nodes.length - 1) {
 
27399                     var a = iD.geo.sphericalDistance(entity.loc, context.entity(nodes[i - 1]).loc),
 
27400                         b = iD.geo.sphericalDistance(entity.loc, context.entity(nodes[i + 1]).loc);
 
27401                     i = a < b ? i - 1 : i + 1;
 
27404                 nextSelectedID = nodes[i];
 
27408         if (nextSelectedID && context.hasEntity(nextSelectedID)) {
 
27409             context.enter(iD.modes.Select(context, [nextSelectedID]));
 
27411             context.enter(iD.modes.Browse(context));
 
27419     operation.available = function() {
 
27423     operation.disabled = function() {
 
27425         if (_.some(selectedIDs, context.hasHiddenConnections)) {
 
27426             reason = 'connected_to_hidden';
 
27428         return action.disabled(context.graph()) || reason;
 
27431     operation.tooltip = function() {
 
27432         var disable = operation.disabled();
 
27434             t('operations.delete.' + disable) :
 
27435             t('operations.delete.description');
 
27438     operation.id = 'delete';
 
27439     operation.keys = [iD.ui.cmd('⌘⌫'), iD.ui.cmd('⌘⌦')];
 
27440     operation.title = t('operations.delete.title');
 
27444 iD.operations.Disconnect = function(selectedIDs, context) {
 
27445     var vertices = _.filter(selectedIDs, function vertex(entityId) {
 
27446         return context.geometry(entityId) === 'vertex';
 
27449     var entityId = vertices[0],
 
27450         action = iD.actions.Disconnect(entityId);
 
27452     if (selectedIDs.length > 1) {
 
27453         action.limitWays(_.without(selectedIDs, entityId));
 
27456     var operation = function() {
 
27457         context.perform(action, t('operations.disconnect.annotation'));
 
27460     operation.available = function() {
 
27461         return vertices.length === 1;
 
27464     operation.disabled = function() {
 
27466         if (_.some(selectedIDs, context.hasHiddenConnections)) {
 
27467             reason = 'connected_to_hidden';
 
27469         return action.disabled(context.graph()) || reason;
 
27472     operation.tooltip = function() {
 
27473         var disable = operation.disabled();
 
27475             t('operations.disconnect.' + disable) :
 
27476             t('operations.disconnect.description');
 
27479     operation.id = 'disconnect';
 
27480     operation.keys = [t('operations.disconnect.key')];
 
27481     operation.title = t('operations.disconnect.title');
 
27485 iD.operations.Merge = function(selectedIDs, context) {
 
27486     var join = iD.actions.Join(selectedIDs),
 
27487         merge = iD.actions.Merge(selectedIDs),
 
27488         mergePolygon = iD.actions.MergePolygon(selectedIDs);
 
27490     var operation = function() {
 
27491         var annotation = t('operations.merge.annotation', {n: selectedIDs.length}),
 
27494         if (!join.disabled(context.graph())) {
 
27496         } else if (!merge.disabled(context.graph())) {
 
27499             action = mergePolygon;
 
27502         context.perform(action, annotation);
 
27503         context.enter(iD.modes.Select(context, selectedIDs.filter(function(id) { return context.hasEntity(id); }))
 
27504             .suppressMenu(true));
 
27507     operation.available = function() {
 
27508         return selectedIDs.length >= 2;
 
27511     operation.disabled = function() {
 
27512         return join.disabled(context.graph()) &&
 
27513             merge.disabled(context.graph()) &&
 
27514             mergePolygon.disabled(context.graph());
 
27517     operation.tooltip = function() {
 
27518         var j = join.disabled(context.graph()),
 
27519             m = merge.disabled(context.graph()),
 
27520             p = mergePolygon.disabled(context.graph());
 
27522         if (j === 'restriction' && m && p)
 
27523             return t('operations.merge.restriction', {relation: context.presets().item('type/restriction').name()});
 
27525         if (p === 'incomplete_relation' && j && m)
 
27526             return t('operations.merge.incomplete_relation');
 
27529             return t('operations.merge.' + j);
 
27531         return t('operations.merge.description');
 
27534     operation.id = 'merge';
 
27535     operation.keys = [t('operations.merge.key')];
 
27536     operation.title = t('operations.merge.title');
 
27540 iD.operations.Move = function(selectedIDs, context) {
 
27541     var extent = selectedIDs.reduce(function(extent, id) {
 
27542             return extent.extend(context.entity(id).extent(context.graph()));
 
27543         }, iD.geo.Extent());
 
27545     var operation = function() {
 
27546         context.enter(iD.modes.Move(context, selectedIDs));
 
27549     operation.available = function() {
 
27550         return selectedIDs.length > 1 ||
 
27551             context.entity(selectedIDs[0]).type !== 'node';
 
27554     operation.disabled = function() {
 
27556         if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
 
27557             reason = 'too_large';
 
27558         } else if (_.some(selectedIDs, context.hasHiddenConnections)) {
 
27559             reason = 'connected_to_hidden';
 
27561         return iD.actions.Move(selectedIDs).disabled(context.graph()) || reason;
 
27564     operation.tooltip = function() {
 
27565         var disable = operation.disabled();
 
27567             t('operations.move.' + disable) :
 
27568             t('operations.move.description');
 
27571     operation.id = 'move';
 
27572     operation.keys = [t('operations.move.key')];
 
27573     operation.title = t('operations.move.title');
 
27577 iD.operations.Orthogonalize = function(selectedIDs, context) {
 
27578     var entityId = selectedIDs[0],
 
27579         entity = context.entity(entityId),
 
27580         extent = entity.extent(context.graph()),
 
27581         geometry = context.geometry(entityId),
 
27582         action = iD.actions.Orthogonalize(entityId, context.projection);
 
27584     var operation = function() {
 
27585         var annotation = t('operations.orthogonalize.annotation.' + geometry);
 
27586         context.perform(action, annotation);
 
27589     operation.available = function() {
 
27590         return selectedIDs.length === 1 &&
 
27591             entity.type === 'way' &&
 
27592             entity.isClosed() &&
 
27593             _.uniq(entity.nodes).length > 2;
 
27596     operation.disabled = function() {
 
27598         if (extent.percentContainedIn(context.extent()) < 0.8) {
 
27599             reason = 'too_large';
 
27600         } else if (context.hasHiddenConnections(entityId)) {
 
27601             reason = 'connected_to_hidden';
 
27603         return action.disabled(context.graph()) || reason;
 
27606     operation.tooltip = function() {
 
27607         var disable = operation.disabled();
 
27609             t('operations.orthogonalize.' + disable) :
 
27610             t('operations.orthogonalize.description.' + geometry);
 
27613     operation.id = 'orthogonalize';
 
27614     operation.keys = [t('operations.orthogonalize.key')];
 
27615     operation.title = t('operations.orthogonalize.title');
 
27619 iD.operations.Reverse = function(selectedIDs, context) {
 
27620     var entityId = selectedIDs[0];
 
27622     var operation = function() {
 
27624             iD.actions.Reverse(entityId),
 
27625             t('operations.reverse.annotation'));
 
27628     operation.available = function() {
 
27629         return selectedIDs.length === 1 &&
 
27630             context.geometry(entityId) === 'line';
 
27633     operation.disabled = function() {
 
27637     operation.tooltip = function() {
 
27638         return t('operations.reverse.description');
 
27641     operation.id = 'reverse';
 
27642     operation.keys = [t('operations.reverse.key')];
 
27643     operation.title = t('operations.reverse.title');
 
27647 iD.operations.Rotate = function(selectedIDs, context) {
 
27648     var entityId = selectedIDs[0],
 
27649         entity = context.entity(entityId),
 
27650         extent = entity.extent(context.graph()),
 
27651         geometry = context.geometry(entityId);
 
27653     var operation = function() {
 
27654         context.enter(iD.modes.RotateWay(context, entityId));
 
27657     operation.available = function() {
 
27658         if (selectedIDs.length !== 1 || entity.type !== 'way')
 
27660         if (geometry === 'area')
 
27662         if (entity.isClosed() &&
 
27663             context.graph().parentRelations(entity).some(function(r) { return r.isMultipolygon(); }))
 
27668     operation.disabled = function() {
 
27669         if (extent.percentContainedIn(context.extent()) < 0.8) {
 
27670             return 'too_large';
 
27671         } else if (context.hasHiddenConnections(entityId)) {
 
27672             return 'connected_to_hidden';
 
27678     operation.tooltip = function() {
 
27679         var disable = operation.disabled();
 
27681             t('operations.rotate.' + disable) :
 
27682             t('operations.rotate.description');
 
27685     operation.id = 'rotate';
 
27686     operation.keys = [t('operations.rotate.key')];
 
27687     operation.title = t('operations.rotate.title');
 
27691 iD.operations.Split = function(selectedIDs, context) {
 
27692     var vertices = _.filter(selectedIDs, function vertex(entityId) {
 
27693         return context.geometry(entityId) === 'vertex';
 
27696     var entityId = vertices[0],
 
27697         action = iD.actions.Split(entityId);
 
27699     if (selectedIDs.length > 1) {
 
27700         action.limitWays(_.without(selectedIDs, entityId));
 
27703     var operation = function() {
 
27706         var ways = action.ways(context.graph());
 
27707         if (ways.length === 1) {
 
27708             annotation = t('operations.split.annotation.' + context.geometry(ways[0].id));
 
27710             annotation = t('operations.split.annotation.multiple', {n: ways.length});
 
27713         var difference = context.perform(action, annotation);
 
27714         context.enter(iD.modes.Select(context, difference.extantIDs()));
 
27717     operation.available = function() {
 
27718         return vertices.length === 1;
 
27721     operation.disabled = function() {
 
27723         if (_.some(selectedIDs, context.hasHiddenConnections)) {
 
27724             reason = 'connected_to_hidden';
 
27726         return action.disabled(context.graph()) || reason;
 
27729     operation.tooltip = function() {
 
27730         var disable = operation.disabled();
 
27732             return t('operations.split.' + disable);
 
27735         var ways = action.ways(context.graph());
 
27736         if (ways.length === 1) {
 
27737             return t('operations.split.description.' + context.geometry(ways[0].id));
 
27739             return t('operations.split.description.multiple');
 
27743     operation.id = 'split';
 
27744     operation.keys = [t('operations.split.key')];
 
27745     operation.title = t('operations.split.title');
 
27749 iD.operations.Straighten = function(selectedIDs, context) {
 
27750     var entityId = selectedIDs[0],
 
27751         action = iD.actions.Straighten(entityId, context.projection);
 
27753     function operation() {
 
27754         var annotation = t('operations.straighten.annotation');
 
27755         context.perform(action, annotation);
 
27758     operation.available = function() {
 
27759         var entity = context.entity(entityId);
 
27760         return selectedIDs.length === 1 &&
 
27761             entity.type === 'way' &&
 
27762             !entity.isClosed() &&
 
27763             _.uniq(entity.nodes).length > 2;
 
27766     operation.disabled = function() {
 
27768         if (context.hasHiddenConnections(entityId)) {
 
27769             reason = 'connected_to_hidden';
 
27771         return action.disabled(context.graph()) || reason;
 
27774     operation.tooltip = function() {
 
27775         var disable = operation.disabled();
 
27777             t('operations.straighten.' + disable) :
 
27778             t('operations.straighten.description');
 
27781     operation.id = 'straighten';
 
27782     operation.keys = [t('operations.straighten.key')];
 
27783     operation.title = t('operations.straighten.title');
 
27787 iD.Connection = function(useHttps) {
 
27788     if (typeof useHttps !== 'boolean') {
 
27789       useHttps = window.location.protocol === 'https:';
 
27792     var event = d3.dispatch('authenticating', 'authenticated', 'auth', 'loading', 'loaded'),
 
27793         protocol = useHttps ? 'https:' : 'http:',
 
27794         url = protocol + '//www.openstreetmap.org',
 
27800             url: protocol + '//www.openstreetmap.org',
 
27801             oauth_consumer_key: '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT',
 
27802             oauth_secret: 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL',
 
27803             loading: authenticating,
 
27804             done: authenticated
 
27808         memberStr = 'member',
 
27811         relationStr = 'relation',
 
27816     connection.changesetURL = function(changesetId) {
 
27817         return url + '/changeset/' + changesetId;
 
27820     connection.changesetsURL = function(center, zoom) {
 
27821         var precision = Math.max(0, Math.ceil(Math.log(zoom) / Math.LN2));
 
27822         return url + '/history#map=' +
 
27823             Math.floor(zoom) + '/' +
 
27824             center[1].toFixed(precision) + '/' +
 
27825             center[0].toFixed(precision);
 
27828     connection.entityURL = function(entity) {
 
27829         return url + '/' + entity.type + '/' + entity.osmId();
 
27832     connection.userURL = function(username) {
 
27833         return url + '/user/' + username;
 
27836     connection.loadFromURL = function(url, callback) {
 
27837         function done(err, dom) {
 
27838             return callback(err, parse(dom));
 
27840         return d3.xml(url).get(done);
 
27843     connection.loadEntity = function(id, callback) {
 
27844         var type = iD.Entity.id.type(id),
 
27845             osmID = iD.Entity.id.toOSM(id);
 
27847         connection.loadFromURL(
 
27848             url + '/api/0.6/' + type + '/' + osmID + (type !== 'node' ? '/full' : ''),
 
27849             function(err, entities) {
 
27850                 if (callback) callback(err, {data: entities});
 
27854     connection.loadEntityVersion = function(id, version, callback) {
 
27855         var type = iD.Entity.id.type(id),
 
27856             osmID = iD.Entity.id.toOSM(id);
 
27858         connection.loadFromURL(
 
27859             url + '/api/0.6/' + type + '/' + osmID + '/' + version,
 
27860             function(err, entities) {
 
27861                 if (callback) callback(err, {data: entities});
 
27865     connection.loadMultiple = function(ids, callback) {
 
27866         _.each(_.groupBy(_.uniq(ids), iD.Entity.id.type), function(v, k) {
 
27867             var type = k + 's',
 
27868                 osmIDs = _.map(v, iD.Entity.id.toOSM);
 
27870             _.each(_.chunk(osmIDs, 150), function(arr) {
 
27871                 connection.loadFromURL(
 
27872                     url + '/api/0.6/' + type + '?' + type + '=' + arr.join(),
 
27873                     function(err, entities) {
 
27874                         if (callback) callback(err, {data: entities});
 
27880     function authenticating() {
 
27881         event.authenticating();
 
27884     function authenticated() {
 
27885         event.authenticated();
 
27888     function getLoc(attrs) {
 
27889         var lon = attrs.lon && attrs.lon.value,
 
27890             lat = attrs.lat && attrs.lat.value;
 
27891         return [parseFloat(lon), parseFloat(lat)];
 
27894     function getNodes(obj) {
 
27895         var elems = obj.getElementsByTagName(ndStr),
 
27896             nodes = new Array(elems.length);
 
27897         for (var i = 0, l = elems.length; i < l; i++) {
 
27898             nodes[i] = 'n' + elems[i].attributes.ref.value;
 
27903     function getTags(obj) {
 
27904         var elems = obj.getElementsByTagName(tagStr),
 
27906         for (var i = 0, l = elems.length; i < l; i++) {
 
27907             var attrs = elems[i].attributes;
 
27908             tags[attrs.k.value] = attrs.v.value;
 
27913     function getMembers(obj) {
 
27914         var elems = obj.getElementsByTagName(memberStr),
 
27915             members = new Array(elems.length);
 
27916         for (var i = 0, l = elems.length; i < l; i++) {
 
27917             var attrs = elems[i].attributes;
 
27919                 id: attrs.type.value[0] + attrs.ref.value,
 
27920                 type: attrs.type.value,
 
27921                 role: attrs.role.value
 
27927     function getVisible(attrs) {
 
27928         return (!attrs.visible || attrs.visible.value !== 'false');
 
27932         node: function nodeData(obj) {
 
27933             var attrs = obj.attributes;
 
27934             return new iD.Node({
 
27935                 id: iD.Entity.id.fromOSM(nodeStr, attrs.id.value),
 
27936                 loc: getLoc(attrs),
 
27937                 version: attrs.version.value,
 
27938                 user: attrs.user && attrs.user.value,
 
27939                 tags: getTags(obj),
 
27940                 visible: getVisible(attrs)
 
27944         way: function wayData(obj) {
 
27945             var attrs = obj.attributes;
 
27946             return new iD.Way({
 
27947                 id: iD.Entity.id.fromOSM(wayStr, attrs.id.value),
 
27948                 version: attrs.version.value,
 
27949                 user: attrs.user && attrs.user.value,
 
27950                 tags: getTags(obj),
 
27951                 nodes: getNodes(obj),
 
27952                 visible: getVisible(attrs)
 
27956         relation: function relationData(obj) {
 
27957             var attrs = obj.attributes;
 
27958             return new iD.Relation({
 
27959                 id: iD.Entity.id.fromOSM(relationStr, attrs.id.value),
 
27960                 version: attrs.version.value,
 
27961                 user: attrs.user && attrs.user.value,
 
27962                 tags: getTags(obj),
 
27963                 members: getMembers(obj),
 
27964                 visible: getVisible(attrs)
 
27969     function parse(dom) {
 
27970         if (!dom || !dom.childNodes) return;
 
27972         var root = dom.childNodes[0],
 
27973             children = root.childNodes,
 
27976         for (var i = 0, l = children.length; i < l; i++) {
 
27977             var child = children[i],
 
27978                 parser = parsers[child.nodeName];
 
27980                 entities.push(parser(child));
 
27987     connection.authenticated = function() {
 
27988         return oauth.authenticated();
 
27991     // Generate Changeset XML. Returns a string.
 
27992     connection.changesetJXON = function(tags) {
 
27996                     tag: _.map(tags, function(value, key) {
 
27997                         return { '@k': key, '@v': value };
 
28006     // Generate [osmChange](http://wiki.openstreetmap.org/wiki/OsmChange)
 
28007     // XML. Returns a string.
 
28008     connection.osmChangeJXON = function(changeset_id, changes) {
 
28009         function nest(x, order) {
 
28011             for (var i = 0; i < x.length; i++) {
 
28012                 var tagName = Object.keys(x[i])[0];
 
28013                 if (!groups[tagName]) groups[tagName] = [];
 
28014                 groups[tagName].push(x[i][tagName]);
 
28017             order.forEach(function(o) {
 
28018                 if (groups[o]) ordered[o] = groups[o];
 
28023         function rep(entity) {
 
28024             return entity.asJXON(changeset_id);
 
28030                 '@generator': 'iD',
 
28031                 'create': nest(changes.created.map(rep), ['node', 'way', 'relation']),
 
28032                 'modify': nest(changes.modified.map(rep), ['node', 'way', 'relation']),
 
28033                 'delete': _.extend(nest(changes.deleted.map(rep), ['relation', 'way', 'node']), {'@if-unused': true})
 
28038     connection.changesetTags = function(comment, imageryUsed) {
 
28039         var detected = iD.detect(),
 
28041                 created_by: 'iD ' + iD.version,
 
28042                 imagery_used: imageryUsed.join(';').substr(0, 255),
 
28043                 host: (window.location.origin + window.location.pathname).substr(0, 255),
 
28044                 locale: detected.locale
 
28048             tags.comment = comment.substr(0, 255);
 
28054     connection.putChangeset = function(changes, comment, imageryUsed, callback) {
 
28057                 path: '/api/0.6/changeset/create',
 
28058                 options: { header: { 'Content-Type': 'text/xml' } },
 
28059                 content: JXON.stringify(connection.changesetJXON(connection.changesetTags(comment, imageryUsed)))
 
28060             }, function(err, changeset_id) {
 
28061                 if (err) return callback(err);
 
28064                     path: '/api/0.6/changeset/' + changeset_id + '/upload',
 
28065                     options: { header: { 'Content-Type': 'text/xml' } },
 
28066                     content: JXON.stringify(connection.osmChangeJXON(changeset_id, changes))
 
28068                     if (err) return callback(err);
 
28069                     // POST was successful, safe to call the callback.
 
28070                     // Still attempt to close changeset, but ignore response because #2667
 
28071                     // Add delay to allow for postgres replication #1646 #2678
 
28072                     window.setTimeout(function() { callback(null, changeset_id); }, 2500);
 
28075                         path: '/api/0.6/changeset/' + changeset_id + '/close',
 
28076                         options: { header: { 'Content-Type': 'text/xml' } }
 
28077                     }, d3.functor(true));
 
28082     connection.userDetails = function(callback) {
 
28084             callback(undefined, userDetails);
 
28088         function done(err, user_details) {
 
28089             if (err) return callback(err);
 
28091             var u = user_details.getElementsByTagName('user')[0],
 
28092                 img = u.getElementsByTagName('img'),
 
28095             if (img && img[0] && img[0].getAttribute('href')) {
 
28096                 image_url = img[0].getAttribute('href');
 
28100                 display_name: u.attributes.display_name.value,
 
28101                 image_url: image_url,
 
28102                 id: u.attributes.id.value
 
28105             callback(undefined, userDetails);
 
28108         oauth.xhr({ method: 'GET', path: '/api/0.6/user/details' }, done);
 
28111     connection.userChangesets = function(callback) {
 
28112         connection.userDetails(function(err, user) {
 
28113             if (err) return callback(err);
 
28115             function done(changesets) {
 
28116                 callback(undefined, Array.prototype.map.call(changesets.getElementsByTagName('changeset'),
 
28117                     function (changeset) {
 
28118                         return { tags: getTags(changeset) };
 
28122             d3.xml(url + '/api/0.6/changesets?user=' + user.id).get()
 
28124                 .on('error', callback);
 
28128     connection.status = function(callback) {
 
28129         function done(capabilities) {
 
28130             var apiStatus = capabilities.getElementsByTagName('status');
 
28131             callback(undefined, apiStatus[0].getAttribute('api'));
 
28133         d3.xml(url + '/api/capabilities').get()
 
28135             .on('error', callback);
 
28138     function abortRequest(i) { i.abort(); }
 
28140     connection.tileZoom = function(_) {
 
28141         if (!arguments.length) return tileZoom;
 
28146     connection.loadTiles = function(projection, dimensions, callback) {
 
28150         var s = projection.scale() * 2 * Math.PI,
 
28151             z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
 
28152             ts = 256 * Math.pow(2, z - tileZoom),
 
28154                 s / 2 - projection.translate()[0],
 
28155                 s / 2 - projection.translate()[1]];
 
28157         var tiles = d3.geo.tile()
 
28158             .scaleExtent([tileZoom, tileZoom])
 
28161             .translate(projection.translate())()
 
28162             .map(function(tile) {
 
28163                 var x = tile[0] * ts - origin[0],
 
28164                     y = tile[1] * ts - origin[1];
 
28167                     id: tile.toString(),
 
28168                     extent: iD.geo.Extent(
 
28169                         projection.invert([x, y + ts]),
 
28170                         projection.invert([x + ts, y]))
 
28174         function bboxUrl(tile) {
 
28175             return url + '/api/0.6/map?bbox=' + tile.extent.toParam();
 
28178         _.filter(inflight, function(v, i) {
 
28179             var wanted = _.find(tiles, function(tile) {
 
28180                 return i === tile.id;
 
28182             if (!wanted) delete inflight[i];
 
28184         }).map(abortRequest);
 
28186         tiles.forEach(function(tile) {
 
28189             if (loadedTiles[id] || inflight[id]) return;
 
28191             if (_.isEmpty(inflight)) {
 
28195             inflight[id] = connection.loadFromURL(bboxUrl(tile), function(err, parsed) {
 
28196                 loadedTiles[id] = true;
 
28197                 delete inflight[id];
 
28199                 if (callback) callback(err, _.extend({data: parsed}, tile));
 
28201                 if (_.isEmpty(inflight)) {
 
28208     connection.switch = function(options) {
 
28210         oauth.options(_.extend({
 
28211             loading: authenticating,
 
28212             done: authenticated
 
28215         connection.flush();
 
28219     connection.toggle = function(_) {
 
28224     connection.flush = function() {
 
28225         userDetails = undefined;
 
28226         _.forEach(inflight, abortRequest);
 
28232     connection.loadedTiles = function(_) {
 
28233         if (!arguments.length) return loadedTiles;
 
28238     connection.logout = function() {
 
28239         userDetails = undefined;
 
28245     connection.authenticate = function(callback) {
 
28246         userDetails = undefined;
 
28247         function done(err, res) {
 
28249             if (callback) callback(err, res);
 
28251         return oauth.authenticate(done);
 
28254     return d3.rebind(connection, event, 'on');
 
28257     iD.Difference represents the difference between two graphs.
 
28258     It knows how to calculate the set of entities that were
 
28259     created, modified, or deleted, and also contains the logic
 
28260     for recursively extending a difference to the complete set
 
28261     of entities that will require a redraw, taking into account
 
28262     child and parent relationships.
 
28264 iD.Difference = function(base, head) {
 
28265     var changes = {}, length = 0;
 
28267     function changed(h, b) {
 
28268         return h !== b && !_.isEqual(_.omit(h, 'v'), _.omit(b, 'v'));
 
28271     _.each(head.entities, function(h, id) {
 
28272         var b = base.entities[id];
 
28273         if (changed(h, b)) {
 
28274             changes[id] = {base: b, head: h};
 
28279     _.each(base.entities, function(b, id) {
 
28280         var h = head.entities[id];
 
28281         if (!changes[id] && changed(h, b)) {
 
28282             changes[id] = {base: b, head: h};
 
28287     function addParents(parents, result) {
 
28288         for (var i = 0; i < parents.length; i++) {
 
28289             var parent = parents[i];
 
28291             if (parent.id in result)
 
28294             result[parent.id] = parent;
 
28295             addParents(head.parentRelations(parent), result);
 
28299     var difference = {};
 
28301     difference.length = function() {
 
28305     difference.changes = function() {
 
28309     difference.extantIDs = function() {
 
28311         _.each(changes, function(change, id) {
 
28312             if (change.head) result.push(id);
 
28317     difference.modified = function() {
 
28319         _.each(changes, function(change) {
 
28320             if (change.base && change.head) result.push(change.head);
 
28325     difference.created = function() {
 
28327         _.each(changes, function(change) {
 
28328             if (!change.base && change.head) result.push(change.head);
 
28333     difference.deleted = function() {
 
28335         _.each(changes, function(change) {
 
28336             if (change.base && !change.head) result.push(change.base);
 
28341     difference.summary = function() {
 
28344         function addEntity(entity, graph, changeType) {
 
28345             relevant[entity.id] = {
 
28348                 changeType: changeType
 
28352         function addParents(entity) {
 
28353             var parents = head.parentWays(entity);
 
28354             for (var j = parents.length - 1; j >= 0; j--) {
 
28355                 var parent = parents[j];
 
28356                 if (!(parent.id in relevant)) addEntity(parent, head, 'modified');
 
28360         _.each(changes, function(change) {
 
28361             if (change.head && change.head.geometry(head) !== 'vertex') {
 
28362                 addEntity(change.head, head, change.base ? 'modified' : 'created');
 
28364             } else if (change.base && change.base.geometry(base) !== 'vertex') {
 
28365                 addEntity(change.base, base, 'deleted');
 
28367             } else if (change.base && change.head) { // modified vertex
 
28368                 var moved    = !_.isEqual(change.base.loc,  change.head.loc),
 
28369                     retagged = !_.isEqual(change.base.tags, change.head.tags);
 
28372                     addParents(change.head);
 
28375                 if (retagged || (moved && change.head.hasInterestingTags())) {
 
28376                     addEntity(change.head, head, 'modified');
 
28379             } else if (change.head && change.head.hasInterestingTags()) { // created vertex
 
28380                 addEntity(change.head, head, 'created');
 
28382             } else if (change.base && change.base.hasInterestingTags()) { // deleted vertex
 
28383                 addEntity(change.base, base, 'deleted');
 
28387         return d3.values(relevant);
 
28390     difference.complete = function(extent) {
 
28391         var result = {}, id, change;
 
28393         for (id in changes) {
 
28394             change = changes[id];
 
28396             var h = change.head,
 
28401                 (!h || !h.intersects(extent, head)) &&
 
28402                 (!b || !b.intersects(extent, base)))
 
28407             if (entity.type === 'way') {
 
28408                 var nh = h ? h.nodes : [],
 
28409                     nb = b ? b.nodes : [],
 
28412                 diff = _.difference(nh, nb);
 
28413                 for (i = 0; i < diff.length; i++) {
 
28414                     result[diff[i]] = head.hasEntity(diff[i]);
 
28417                 diff = _.difference(nb, nh);
 
28418                 for (i = 0; i < diff.length; i++) {
 
28419                     result[diff[i]] = head.hasEntity(diff[i]);
 
28423             addParents(head.parentWays(entity), result);
 
28424             addParents(head.parentRelations(entity), result);
 
28432 iD.Entity = function(attrs) {
 
28433     // For prototypal inheritance.
 
28434     if (this instanceof iD.Entity) return;
 
28436     // Create the appropriate subtype.
 
28437     if (attrs && attrs.type) {
 
28438         return iD.Entity[attrs.type].apply(this, arguments);
 
28439     } else if (attrs && attrs.id) {
 
28440         return iD.Entity[iD.Entity.id.type(attrs.id)].apply(this, arguments);
 
28443     // Initialize a generic Entity (used only in tests).
 
28444     return (new iD.Entity()).initialize(arguments);
 
28447 iD.Entity.id = function(type) {
 
28448     return iD.Entity.id.fromOSM(type, iD.Entity.id.next[type]--);
 
28451 iD.Entity.id.next = {node: -1, way: -1, relation: -1};
 
28453 iD.Entity.id.fromOSM = function(type, id) {
 
28454     return type[0] + id;
 
28457 iD.Entity.id.toOSM = function(id) {
 
28458     return id.slice(1);
 
28461 iD.Entity.id.type = function(id) {
 
28462     return {'n': 'node', 'w': 'way', 'r': 'relation'}[id[0]];
 
28465 // A function suitable for use as the second argument to d3.selection#data().
 
28466 iD.Entity.key = function(entity) {
 
28467     return entity.id + 'v' + (entity.v || 0);
 
28470 iD.Entity.prototype = {
 
28473     initialize: function(sources) {
 
28474         for (var i = 0; i < sources.length; ++i) {
 
28475             var source = sources[i];
 
28476             for (var prop in source) {
 
28477                 if (Object.prototype.hasOwnProperty.call(source, prop)) {
 
28478                     if (source[prop] === undefined) {
 
28481                         this[prop] = source[prop];
 
28487         if (!this.id && this.type) {
 
28488             this.id = iD.Entity.id(this.type);
 
28490         if (!this.hasOwnProperty('visible')) {
 
28491             this.visible = true;
 
28495             Object.freeze(this);
 
28496             Object.freeze(this.tags);
 
28498             if (this.loc) Object.freeze(this.loc);
 
28499             if (this.nodes) Object.freeze(this.nodes);
 
28500             if (this.members) Object.freeze(this.members);
 
28506     copy: function(resolver, copies) {
 
28507         if (copies[this.id])
 
28508             return copies[this.id];
 
28510         var copy = iD.Entity(this, {id: undefined, user: undefined, version: undefined});
 
28511         copies[this.id] = copy;
 
28516     osmId: function() {
 
28517         return iD.Entity.id.toOSM(this.id);
 
28520     isNew: function() {
 
28521         return this.osmId() < 0;
 
28524     update: function(attrs) {
 
28525         return iD.Entity(this, attrs, {v: 1 + (this.v || 0)});
 
28528     mergeTags: function(tags) {
 
28529         var merged = _.clone(this.tags), changed = false;
 
28530         for (var k in tags) {
 
28531             var t1 = merged[k],
 
28536             } else if (t1 !== t2) {
 
28538                 merged[k] = _.union(t1.split(/;\s*/), t2.split(/;\s*/)).join(';');
 
28541         return changed ? this.update({tags: merged}) : this;
 
28544     intersects: function(extent, resolver) {
 
28545         return this.extent(resolver).intersects(extent);
 
28548     isUsed: function(resolver) {
 
28549         return _.without(Object.keys(this.tags), 'area').length > 0 ||
 
28550             resolver.parentRelations(this).length > 0;
 
28553     hasInterestingTags: function() {
 
28554         return _.keys(this.tags).some(iD.interestingTag);
 
28557     isHighwayIntersection: function() {
 
28561     deprecatedTags: function() {
 
28562         var tags = _.toPairs(this.tags);
 
28563         var deprecated = {};
 
28565         iD.data.deprecated.forEach(function(d) {
 
28566             var match = _.toPairs(d.old)[0];
 
28567             tags.forEach(function(t) {
 
28568                 if (t[0] === match[0] &&
 
28569                     (t[1] === match[1] || match[1] === '*')) {
 
28570                     deprecated[t[0]] = t[1];
 
28578 iD.Graph = function(other, mutable) {
 
28579     if (!(this instanceof iD.Graph)) return new iD.Graph(other, mutable);
 
28581     if (other instanceof iD.Graph) {
 
28582         var base = other.base();
 
28583         this.entities = _.assign(Object.create(base.entities), other.entities);
 
28584         this._parentWays = _.assign(Object.create(base.parentWays), other._parentWays);
 
28585         this._parentRels = _.assign(Object.create(base.parentRels), other._parentRels);
 
28588         this.entities = Object.create({});
 
28589         this._parentWays = Object.create({});
 
28590         this._parentRels = Object.create({});
 
28591         this.rebase(other || [], [this]);
 
28594     this.transients = {};
 
28595     this._childNodes = {};
 
28596     this.frozen = !mutable;
 
28599 iD.Graph.prototype = {
 
28600     hasEntity: function(id) {
 
28601         return this.entities[id];
 
28604     entity: function(id) {
 
28605         var entity = this.entities[id];
 
28607             throw new Error('entity ' + id + ' not found');
 
28612     transient: function(entity, key, fn) {
 
28613         var id = entity.id,
 
28614             transients = this.transients[id] ||
 
28615             (this.transients[id] = {});
 
28617         if (transients[key] !== undefined) {
 
28618             return transients[key];
 
28621         transients[key] = fn.call(entity);
 
28623         return transients[key];
 
28626     parentWays: function(entity) {
 
28627         var parents = this._parentWays[entity.id],
 
28631             for (var i = 0; i < parents.length; i++) {
 
28632                 result.push(this.entity(parents[i]));
 
28638     isPoi: function(entity) {
 
28639         var parentWays = this._parentWays[entity.id];
 
28640         return !parentWays || parentWays.length === 0;
 
28643     isShared: function(entity) {
 
28644         var parentWays = this._parentWays[entity.id];
 
28645         return parentWays && parentWays.length > 1;
 
28648     parentRelations: function(entity) {
 
28649         var parents = this._parentRels[entity.id],
 
28653             for (var i = 0; i < parents.length; i++) {
 
28654                 result.push(this.entity(parents[i]));
 
28660     childNodes: function(entity) {
 
28661         if (this._childNodes[entity.id]) return this._childNodes[entity.id];
 
28662         if (!entity.nodes) return [];
 
28665         for (var i = 0; i < entity.nodes.length; i++) {
 
28666             nodes[i] = this.entity(entity.nodes[i]);
 
28669         if (iD.debug) Object.freeze(nodes);
 
28671         this._childNodes[entity.id] = nodes;
 
28672         return this._childNodes[entity.id];
 
28677             'entities': iD.util.getPrototypeOf(this.entities),
 
28678             'parentWays': iD.util.getPrototypeOf(this._parentWays),
 
28679             'parentRels': iD.util.getPrototypeOf(this._parentRels)
 
28683     // Unlike other graph methods, rebase mutates in place. This is because it
 
28684     // is used only during the history operation that merges newly downloaded
 
28685     // data into each state. To external consumers, it should appear as if the
 
28686     // graph always contained the newly downloaded data.
 
28687     rebase: function(entities, stack, force) {
 
28688         var base = this.base(),
 
28691         for (i = 0; i < entities.length; i++) {
 
28692             var entity = entities[i];
 
28694             if (!entity.visible || (!force && base.entities[entity.id]))
 
28697             // Merging data into the base graph
 
28698             base.entities[entity.id] = entity;
 
28699             this._updateCalculated(undefined, entity, base.parentWays, base.parentRels);
 
28701             // Restore provisionally-deleted nodes that are discovered to have an extant parent
 
28702             if (entity.type === 'way') {
 
28703                 for (j = 0; j < entity.nodes.length; j++) {
 
28704                     id = entity.nodes[j];
 
28705                     for (k = 1; k < stack.length; k++) {
 
28706                         var ents = stack[k].entities;
 
28707                         if (ents.hasOwnProperty(id) && ents[id] === undefined) {
 
28715         for (i = 0; i < stack.length; i++) {
 
28716             stack[i]._updateRebased();
 
28720     _updateRebased: function() {
 
28721         var base = this.base(),
 
28722             i, k, child, id, keys;
 
28724         keys = Object.keys(this._parentWays);
 
28725         for (i = 0; i < keys.length; i++) {
 
28727             if (base.parentWays[child]) {
 
28728                 for (k = 0; k < base.parentWays[child].length; k++) {
 
28729                     id = base.parentWays[child][k];
 
28730                     if (!this.entities.hasOwnProperty(id) && !_.includes(this._parentWays[child], id)) {
 
28731                         this._parentWays[child].push(id);
 
28737         keys = Object.keys(this._parentRels);
 
28738         for (i = 0; i < keys.length; i++) {
 
28740             if (base.parentRels[child]) {
 
28741                 for (k = 0; k < base.parentRels[child].length; k++) {
 
28742                     id = base.parentRels[child][k];
 
28743                     if (!this.entities.hasOwnProperty(id) && !_.includes(this._parentRels[child], id)) {
 
28744                         this._parentRels[child].push(id);
 
28750         this.transients = {};
 
28752         // this._childNodes is not updated, under the assumption that
 
28753         // ways are always downloaded with their child nodes.
 
28756     // Updates calculated properties (parentWays, parentRels) for the specified change
 
28757     _updateCalculated: function(oldentity, entity, parentWays, parentRels) {
 
28759         parentWays = parentWays || this._parentWays;
 
28760         parentRels = parentRels || this._parentRels;
 
28762         var type = entity && entity.type || oldentity && oldentity.type,
 
28763             removed, added, ways, rels, i;
 
28766         if (type === 'way') {
 
28768             // Update parentWays
 
28769             if (oldentity && entity) {
 
28770                 removed = _.difference(oldentity.nodes, entity.nodes);
 
28771                 added = _.difference(entity.nodes, oldentity.nodes);
 
28772             } else if (oldentity) {
 
28773                 removed = oldentity.nodes;
 
28775             } else if (entity) {
 
28777                 added = entity.nodes;
 
28779             for (i = 0; i < removed.length; i++) {
 
28780                 parentWays[removed[i]] = _.without(parentWays[removed[i]], oldentity.id);
 
28782             for (i = 0; i < added.length; i++) {
 
28783                 ways = _.without(parentWays[added[i]], entity.id);
 
28784                 ways.push(entity.id);
 
28785                 parentWays[added[i]] = ways;
 
28788         } else if (type === 'relation') {
 
28790             // Update parentRels
 
28791             if (oldentity && entity) {
 
28792                 removed = _.difference(oldentity.members, entity.members);
 
28793                 added = _.difference(entity.members, oldentity);
 
28794             } else if (oldentity) {
 
28795                 removed = oldentity.members;
 
28797             } else if (entity) {
 
28799                 added = entity.members;
 
28801             for (i = 0; i < removed.length; i++) {
 
28802                 parentRels[removed[i].id] = _.without(parentRels[removed[i].id], oldentity.id);
 
28804             for (i = 0; i < added.length; i++) {
 
28805                 rels = _.without(parentRels[added[i].id], entity.id);
 
28806                 rels.push(entity.id);
 
28807                 parentRels[added[i].id] = rels;
 
28812     replace: function(entity) {
 
28813         if (this.entities[entity.id] === entity)
 
28816         return this.update(function() {
 
28817             this._updateCalculated(this.entities[entity.id], entity);
 
28818             this.entities[entity.id] = entity;
 
28822     remove: function(entity) {
 
28823         return this.update(function() {
 
28824             this._updateCalculated(entity, undefined);
 
28825             this.entities[entity.id] = undefined;
 
28829     revert: function(id) {
 
28830         var baseEntity = this.base().entities[id],
 
28831             headEntity = this.entities[id];
 
28833         if (headEntity === baseEntity)
 
28836         return this.update(function() {
 
28837             this._updateCalculated(headEntity, baseEntity);
 
28838             delete this.entities[id];
 
28842     update: function() {
 
28843         var graph = this.frozen ? iD.Graph(this, true) : this;
 
28845         for (var i = 0; i < arguments.length; i++) {
 
28846             arguments[i].call(graph, graph);
 
28849         if (this.frozen) graph.frozen = true;
 
28854     // Obliterates any existing entities
 
28855     load: function(entities) {
 
28856         var base = this.base();
 
28857         this.entities = Object.create(base.entities);
 
28859         for (var i in entities) {
 
28860             this.entities[i] = entities[i];
 
28861             this._updateCalculated(base.entities[i], this.entities[i]);
 
28867 iD.History = function(context) {
 
28868     var stack, index, tree,
 
28869         imageryUsed = ['Bing'],
 
28870         dispatch = d3.dispatch('change', 'undone', 'redone'),
 
28871         lock = iD.util.SessionMutex('lock');
 
28873     function perform(actions) {
 
28874         actions = Array.prototype.slice.call(actions);
 
28878         if (!_.isFunction(_.last(actions))) {
 
28879             annotation = actions.pop();
 
28882         var graph = stack[index].graph;
 
28883         for (var i = 0; i < actions.length; i++) {
 
28884             graph = actions[i](graph);
 
28889             annotation: annotation,
 
28890             imageryUsed: imageryUsed
 
28894     function change(previous) {
 
28895         var difference = iD.Difference(previous, history.graph());
 
28896         dispatch.change(difference);
 
28900     // iD uses namespaced keys so multiple installations do not conflict
 
28901     function getKey(n) {
 
28902         return 'iD_' + window.location.origin + '_' + n;
 
28906         graph: function() {
 
28907             return stack[index].graph;
 
28911             return stack[0].graph;
 
28914         merge: function(entities, extent) {
 
28915             stack[0].graph.rebase(entities, _.map(stack, 'graph'), false);
 
28916             tree.rebase(entities, false);
 
28918             dispatch.change(undefined, extent);
 
28921         perform: function() {
 
28922             var previous = stack[index].graph;
 
28924             stack = stack.slice(0, index + 1);
 
28925             stack.push(perform(arguments));
 
28928             return change(previous);
 
28931         replace: function() {
 
28932             var previous = stack[index].graph;
 
28934             // assert(index == stack.length - 1)
 
28935             stack[index] = perform(arguments);
 
28937             return change(previous);
 
28941             var previous = stack[index].graph;
 
28946                 return change(previous);
 
28950         // Same as calling pop and then perform
 
28951         overwrite: function() {
 
28952             var previous = stack[index].graph;
 
28958             stack = stack.slice(0, index + 1);
 
28959             stack.push(perform(arguments));
 
28962             return change(previous);
 
28966             var previous = stack[index].graph;
 
28968             // Pop to the next annotated state.
 
28969             while (index > 0) {
 
28971                 if (stack[index].annotation) break;
 
28975             return change(previous);
 
28979             var previous = stack[index].graph;
 
28981             while (index < stack.length - 1) {
 
28983                 if (stack[index].annotation) break;
 
28987             return change(previous);
 
28990         undoAnnotation: function() {
 
28993                 if (stack[i].annotation) return stack[i].annotation;
 
28998         redoAnnotation: function() {
 
29000             while (i <= stack.length - 1) {
 
29001                 if (stack[i].annotation) return stack[i].annotation;
 
29006         intersects: function(extent) {
 
29007             return tree.intersects(extent, stack[index].graph);
 
29010         difference: function() {
 
29011             var base = stack[0].graph,
 
29012                 head = stack[index].graph;
 
29013             return iD.Difference(base, head);
 
29016         changes: function(action) {
 
29017             var base = stack[0].graph,
 
29018                 head = stack[index].graph;
 
29021                 head = action(head);
 
29024             var difference = iD.Difference(base, head);
 
29027                 modified: difference.modified(),
 
29028                 created: difference.created(),
 
29029                 deleted: difference.deleted()
 
29033         validate: function(changes) {
 
29034             return _(iD.validations)
 
29035                 .map(function(fn) { return fn()(changes, stack[index].graph); })
 
29040         hasChanges: function() {
 
29041             return this.difference().length() > 0;
 
29044         imageryUsed: function(sources) {
 
29046                 imageryUsed = sources;
 
29049                 return _(stack.slice(1, index + 1))
 
29050                     .map('imageryUsed')
 
29053                     .without(undefined, 'Custom')
 
29058         reset: function() {
 
29059             stack = [{graph: iD.Graph()}];
 
29061             tree = iD.Tree(stack[0].graph);
 
29066         toJSON: function() {
 
29067             if (!this.hasChanges()) return;
 
29069             var allEntities = {},
 
29073             var s = stack.map(function(i) {
 
29074                 var modified = [], deleted = [];
 
29076                 _.forEach(i.graph.entities, function(entity, id) {
 
29078                         var key = iD.Entity.key(entity);
 
29079                         allEntities[key] = entity;
 
29080                         modified.push(key);
 
29085                     // make sure that the originals of changed or deleted entities get merged
 
29086                     // into the base of the stack after restoring the data from JSON.
 
29087                     if (id in base.graph.entities) {
 
29088                         baseEntities[id] = base.graph.entities[id];
 
29090                     // get originals of parent entities too
 
29091                     _.forEach(base.graph._parentWays[id], function(parentId) {
 
29092                         if (parentId in base.graph.entities) {
 
29093                             baseEntities[parentId] = base.graph.entities[parentId];
 
29100                 if (modified.length) x.modified = modified;
 
29101                 if (deleted.length) x.deleted = deleted;
 
29102                 if (i.imageryUsed) x.imageryUsed = i.imageryUsed;
 
29103                 if (i.annotation) x.annotation = i.annotation;
 
29108             return JSON.stringify({
 
29110                 entities: _.values(allEntities),
 
29111                 baseEntities: _.values(baseEntities),
 
29113                 nextIDs: iD.Entity.id.next,
 
29118         fromJSON: function(json, loadChildNodes) {
 
29119             var h = JSON.parse(json),
 
29120                 loadComplete = true;
 
29122             iD.Entity.id.next = h.nextIDs;
 
29125             if (h.version === 2 || h.version === 3) {
 
29126                 var allEntities = {};
 
29128                 h.entities.forEach(function(entity) {
 
29129                     allEntities[iD.Entity.key(entity)] = iD.Entity(entity);
 
29132                 if (h.version === 3) {
 
29133                     // This merges originals for changed entities into the base of
 
29134                     // the stack even if the current stack doesn't have them (for
 
29135                     // example when iD has been restarted in a different region)
 
29136                     var baseEntities = h.baseEntities.map(function(d) { return iD.Entity(d); });
 
29137                     stack[0].graph.rebase(baseEntities, _.map(stack, 'graph'), true);
 
29138                     tree.rebase(baseEntities, true);
 
29140                     // When we restore a modified way, we also need to fetch any missing
 
29141                     // childnodes that would normally have been downloaded with it.. #2142
 
29142                     if (loadChildNodes) {
 
29143                         var missing =  _(baseEntities)
 
29144                                 .filter({ type: 'way' })
 
29148                                 .reject(function(n) { return stack[0].graph.hasEntity(n); })
 
29151                         if (!_.isEmpty(missing)) {
 
29152                             loadComplete = false;
 
29153                             context.redrawEnable(false);
 
29155                             var loading = iD.ui.Loading(context).blocking(true);
 
29156                             context.container().call(loading);
 
29158                             var childNodesLoaded = function(err, result) {
 
29160                                     var visible = _.groupBy(result.data, 'visible');
 
29161                                     if (!_.isEmpty(visible.true)) {
 
29162                                         missing = _.difference(missing, _.map(visible.true, 'id'));
 
29163                                         stack[0].graph.rebase(visible.true, _.map(stack, 'graph'), true);
 
29164                                         tree.rebase(visible.true, true);
 
29167                                     // fetch older versions of nodes that were deleted..
 
29168                                     _.each(visible.false, function(entity) {
 
29169                                         context.connection()
 
29170                                             .loadEntityVersion(entity.id, +entity.version - 1, childNodesLoaded);
 
29174                                 if (err || _.isEmpty(missing)) {
 
29176                                     context.redrawEnable(true);
 
29181                             context.connection().loadMultiple(missing, childNodesLoaded);
 
29186                 stack = h.stack.map(function(d) {
 
29187                     var entities = {}, entity;
 
29190                         d.modified.forEach(function(key) {
 
29191                             entity = allEntities[key];
 
29192                             entities[entity.id] = entity;
 
29197                         d.deleted.forEach(function(id) {
 
29198                             entities[id] = undefined;
 
29203                         graph: iD.Graph(stack[0].graph).load(entities),
 
29204                         annotation: d.annotation,
 
29205                         imageryUsed: d.imageryUsed
 
29209             } else { // original version
 
29210                 stack = h.stack.map(function(d) {
 
29213                     for (var i in d.entities) {
 
29214                         var entity = d.entities[i];
 
29215                         entities[i] = entity === 'undefined' ? undefined : iD.Entity(entity);
 
29218                     d.graph = iD.Graph(stack[0].graph).load(entities);
 
29223             if (loadComplete) {
 
29231             if (lock.locked()) context.storage(getKey('saved_history'), history.toJSON() || null);
 
29235         clearSaved: function() {
 
29236             context.debouncedSave.cancel();
 
29237             if (lock.locked()) context.storage(getKey('saved_history'), null);
 
29242             return lock.lock();
 
29245         unlock: function() {
 
29249         // is iD not open in another window and it detects that
 
29250         // there's a history stored in localStorage that's recoverable?
 
29251         restorableChanges: function() {
 
29252             return lock.locked() && !!context.storage(getKey('saved_history'));
 
29255         // load history from a version stored in localStorage
 
29256         restore: function() {
 
29257             if (!lock.locked()) return;
 
29259             var json = context.storage(getKey('saved_history'));
 
29260             if (json) history.fromJSON(json, true);
 
29269     return d3.rebind(history, dispatch, 'on');
 
29271 iD.Node = iD.Entity.node = function iD_Node() {
 
29272     if (!(this instanceof iD_Node)) {
 
29273         return (new iD_Node()).initialize(arguments);
 
29274     } else if (arguments.length) {
 
29275         this.initialize(arguments);
 
29279 iD.Node.prototype = Object.create(iD.Entity.prototype);
 
29281 _.extend(iD.Node.prototype, {
 
29284     extent: function() {
 
29285         return new iD.geo.Extent(this.loc);
 
29288     geometry: function(graph) {
 
29289         return graph.transient(this, 'geometry', function() {
 
29290             return graph.isPoi(this) ? 'point' : 'vertex';
 
29294     move: function(loc) {
 
29295         return this.update({loc: loc});
 
29298     isIntersection: function(resolver) {
 
29299         return resolver.transient(this, 'isIntersection', function() {
 
29300             return resolver.parentWays(this).filter(function(parent) {
 
29301                 return (parent.tags.highway ||
 
29302                     parent.tags.waterway ||
 
29303                     parent.tags.railway ||
 
29304                     parent.tags.aeroway) &&
 
29305                     parent.geometry(resolver) === 'line';
 
29310     isHighwayIntersection: function(resolver) {
 
29311         return resolver.transient(this, 'isHighwayIntersection', function() {
 
29312             return resolver.parentWays(this).filter(function(parent) {
 
29313                 return parent.tags.highway && parent.geometry(resolver) === 'line';
 
29318     isOnAddressLine: function(resolver) {
 
29319         return resolver.transient(this, 'isOnAddressLine', function() {
 
29320             return resolver.parentWays(this).filter(function(parent) {
 
29321                 return parent.tags.hasOwnProperty('addr:interpolation') &&
 
29322                     parent.geometry(resolver) === 'line';
 
29327     asJXON: function(changeset_id) {
 
29330                 '@id': this.osmId(),
 
29331                 '@lon': this.loc[0],
 
29332                 '@lat': this.loc[1],
 
29333                 '@version': (this.version || 0),
 
29334                 tag: _.map(this.tags, function(v, k) {
 
29335                     return { keyAttributes: { k: k, v: v } };
 
29339         if (changeset_id) r.node['@changeset'] = changeset_id;
 
29343     asGeoJSON: function() {
 
29346             coordinates: this.loc
 
29350 iD.Relation = iD.Entity.relation = function iD_Relation() {
 
29351     if (!(this instanceof iD_Relation)) {
 
29352         return (new iD_Relation()).initialize(arguments);
 
29353     } else if (arguments.length) {
 
29354         this.initialize(arguments);
 
29358 iD.Relation.prototype = Object.create(iD.Entity.prototype);
 
29360 iD.Relation.creationOrder = function(a, b) {
 
29361     var aId = parseInt(iD.Entity.id.toOSM(a.id), 10);
 
29362     var bId = parseInt(iD.Entity.id.toOSM(b.id), 10);
 
29364     if (aId < 0 || bId < 0) return aId - bId;
 
29368 _.extend(iD.Relation.prototype, {
 
29372     copy: function(resolver, copies) {
 
29373         if (copies[this.id])
 
29374             return copies[this.id];
 
29376         var copy = iD.Entity.prototype.copy.call(this, resolver, copies);
 
29378         var members = this.members.map(function(member) {
 
29379             return _.extend({}, member, {id: resolver.entity(member.id).copy(resolver, copies).id});
 
29382         copy = copy.update({members: members});
 
29383         copies[this.id] = copy;
 
29388     extent: function(resolver, memo) {
 
29389         return resolver.transient(this, 'extent', function() {
 
29390             if (memo && memo[this.id]) return iD.geo.Extent();
 
29392             memo[this.id] = true;
 
29394             var extent = iD.geo.Extent();
 
29395             for (var i = 0; i < this.members.length; i++) {
 
29396                 var member = resolver.hasEntity(this.members[i].id);
 
29398                     extent._extend(member.extent(resolver, memo));
 
29405     geometry: function(graph) {
 
29406         return graph.transient(this, 'geometry', function() {
 
29407             return this.isMultipolygon() ? 'area' : 'relation';
 
29411     isDegenerate: function() {
 
29412         return this.members.length === 0;
 
29415     // Return an array of members, each extended with an 'index' property whose value
 
29416     // is the member index.
 
29417     indexedMembers: function() {
 
29418         var result = new Array(this.members.length);
 
29419         for (var i = 0; i < this.members.length; i++) {
 
29420             result[i] = _.extend({}, this.members[i], {index: i});
 
29425     // Return the first member with the given role. A copy of the member object
 
29426     // is returned, extended with an 'index' property whose value is the member index.
 
29427     memberByRole: function(role) {
 
29428         for (var i = 0; i < this.members.length; i++) {
 
29429             if (this.members[i].role === role) {
 
29430                 return _.extend({}, this.members[i], {index: i});
 
29435     // Return the first member with the given id. A copy of the member object
 
29436     // is returned, extended with an 'index' property whose value is the member index.
 
29437     memberById: function(id) {
 
29438         for (var i = 0; i < this.members.length; i++) {
 
29439             if (this.members[i].id === id) {
 
29440                 return _.extend({}, this.members[i], {index: i});
 
29445     // Return the first member with the given id and role. A copy of the member object
 
29446     // is returned, extended with an 'index' property whose value is the member index.
 
29447     memberByIdAndRole: function(id, role) {
 
29448         for (var i = 0; i < this.members.length; i++) {
 
29449             if (this.members[i].id === id && this.members[i].role === role) {
 
29450                 return _.extend({}, this.members[i], {index: i});
 
29455     addMember: function(member, index) {
 
29456         var members = this.members.slice();
 
29457         members.splice(index === undefined ? members.length : index, 0, member);
 
29458         return this.update({members: members});
 
29461     updateMember: function(member, index) {
 
29462         var members = this.members.slice();
 
29463         members.splice(index, 1, _.extend({}, members[index], member));
 
29464         return this.update({members: members});
 
29467     removeMember: function(index) {
 
29468         var members = this.members.slice();
 
29469         members.splice(index, 1);
 
29470         return this.update({members: members});
 
29473     removeMembersWithID: function(id) {
 
29474         var members = _.reject(this.members, function(m) { return m.id === id; });
 
29475         return this.update({members: members});
 
29478     // Wherever a member appears with id `needle.id`, replace it with a member
 
29479     // with id `replacement.id`, type `replacement.type`, and the original role,
 
29480     // unless a member already exists with that id and role. Return an updated
 
29482     replaceMember: function(needle, replacement) {
 
29483         if (!this.memberById(needle.id))
 
29488         for (var i = 0; i < this.members.length; i++) {
 
29489             var member = this.members[i];
 
29490             if (member.id !== needle.id) {
 
29491                 members.push(member);
 
29492             } else if (!this.memberByIdAndRole(replacement.id, member.role)) {
 
29493                 members.push({id: replacement.id, type: replacement.type, role: member.role});
 
29497         return this.update({members: members});
 
29500     asJXON: function(changeset_id) {
 
29503                 '@id': this.osmId(),
 
29504                 '@version': this.version || 0,
 
29505                 member: _.map(this.members, function(member) {
 
29506                     return { keyAttributes: { type: member.type, role: member.role, ref: iD.Entity.id.toOSM(member.id) } };
 
29508                 tag: _.map(this.tags, function(v, k) {
 
29509                     return { keyAttributes: { k: k, v: v } };
 
29513         if (changeset_id) r.relation['@changeset'] = changeset_id;
 
29517     asGeoJSON: function(resolver) {
 
29518         return resolver.transient(this, 'GeoJSON', function () {
 
29519             if (this.isMultipolygon()) {
 
29521                     type: 'MultiPolygon',
 
29522                     coordinates: this.multipolygon(resolver)
 
29526                     type: 'FeatureCollection',
 
29527                     properties: this.tags,
 
29528                     features: this.members.map(function (member) {
 
29529                         return _.extend({role: member.role}, resolver.entity(member.id).asGeoJSON(resolver));
 
29536     area: function(resolver) {
 
29537         return resolver.transient(this, 'area', function() {
 
29538             return d3.geo.area(this.asGeoJSON(resolver));
 
29542     isMultipolygon: function() {
 
29543         return this.tags.type === 'multipolygon';
 
29546     isComplete: function(resolver) {
 
29547         for (var i = 0; i < this.members.length; i++) {
 
29548             if (!resolver.hasEntity(this.members[i].id)) {
 
29555     isRestriction: function() {
 
29556         return !!(this.tags.type && this.tags.type.match(/^restriction:?/));
 
29559     // Returns an array [A0, ... An], each Ai being an array of node arrays [Nds0, ... Ndsm],
 
29560     // where Nds0 is an outer ring and subsequent Ndsi's (if any i > 0) being inner rings.
 
29562     // This corresponds to the structure needed for rendering a multipolygon path using a
 
29563     // `evenodd` fill rule, as well as the structure of a GeoJSON MultiPolygon geometry.
 
29565     // In the case of invalid geometries, this function will still return a result which
 
29566     // includes the nodes of all way members, but some Nds may be unclosed and some inner
 
29567     // rings not matched with the intended outer ring.
 
29569     multipolygon: function(resolver) {
 
29570         var outers = this.members.filter(function(m) { return 'outer' === (m.role || 'outer'); }),
 
29571             inners = this.members.filter(function(m) { return 'inner' === m.role; });
 
29573         outers = iD.geo.joinWays(outers, resolver);
 
29574         inners = iD.geo.joinWays(inners, resolver);
 
29576         outers = outers.map(function(outer) { return _.map(outer.nodes, 'loc'); });
 
29577         inners = inners.map(function(inner) { return _.map(inner.nodes, 'loc'); });
 
29579         var result = outers.map(function(o) {
 
29580             // Heuristic for detecting counterclockwise winding order. Assumes
 
29581             // that OpenStreetMap polygons are not hemisphere-spanning.
 
29582             return [d3.geo.area({type: 'Polygon', coordinates: [o]}) > 2 * Math.PI ? o.reverse() : o];
 
29585         function findOuter(inner) {
 
29588             for (o = 0; o < outers.length; o++) {
 
29590                 if (iD.geo.polygonContainsPolygon(outer, inner))
 
29594             for (o = 0; o < outers.length; o++) {
 
29596                 if (iD.geo.polygonIntersectsPolygon(outer, inner))
 
29601         for (var i = 0; i < inners.length; i++) {
 
29602             var inner = inners[i];
 
29604             if (d3.geo.area({type: 'Polygon', coordinates: [inner]}) < 2 * Math.PI) {
 
29605                 inner = inner.reverse();
 
29608             var o = findOuter(inners[i]);
 
29609             if (o !== undefined)
 
29610                 result[o].push(inners[i]);
 
29612                 result.push([inners[i]]); // Invalid geometry
 
29620         'chair_lift': true,
 
29621         'mixed_lift': true,
 
29626         'magic_carpet': true,
 
29631         'motorway_link': true
 
29637         'piste:halfpipe': true
 
29661 iD.interestingTag = function (key) {
 
29662     return key !== 'attribution' &&
 
29663         key !== 'created_by' &&
 
29664         key !== 'source' &&
 
29666         key.indexOf('tiger:') !== 0;
 
29669 iD.Tree = function(head) {
 
29670     var rtree = rbush(),
 
29673     function entityRectangle(entity) {
 
29674         var rect = entity.extent(head).rectangle();
 
29675         rect.id = entity.id;
 
29676         rectangles[entity.id] = rect;
 
29680     function updateParents(entity, insertions, memo) {
 
29681         head.parentWays(entity).forEach(function(way) {
 
29682             if (rectangles[way.id]) {
 
29683                 rtree.remove(rectangles[way.id]);
 
29684                 insertions[way.id] = way;
 
29686             updateParents(way, insertions, memo);
 
29689         head.parentRelations(entity).forEach(function(relation) {
 
29690             if (memo[entity.id]) return;
 
29691             memo[entity.id] = true;
 
29692             if (rectangles[relation.id]) {
 
29693                 rtree.remove(rectangles[relation.id]);
 
29694                 insertions[relation.id] = relation;
 
29696             updateParents(relation, insertions, memo);
 
29702     tree.rebase = function(entities, force) {
 
29703         var insertions = {};
 
29705         for (var i = 0; i < entities.length; i++) {
 
29706             var entity = entities[i];
 
29708             if (!entity.visible)
 
29711             if (head.entities.hasOwnProperty(entity.id) || rectangles[entity.id]) {
 
29714                 } else if (rectangles[entity.id]) {
 
29715                     rtree.remove(rectangles[entity.id]);
 
29719             insertions[entity.id] = entity;
 
29720             updateParents(entity, insertions, {});
 
29723         rtree.load(_.map(insertions, entityRectangle));
 
29728     tree.intersects = function(extent, graph) {
 
29729         if (graph !== head) {
 
29730             var diff = iD.Difference(head, graph),
 
29735             diff.deleted().forEach(function(entity) {
 
29736                 rtree.remove(rectangles[entity.id]);
 
29737                 delete rectangles[entity.id];
 
29740             diff.modified().forEach(function(entity) {
 
29741                 rtree.remove(rectangles[entity.id]);
 
29742                 insertions[entity.id] = entity;
 
29743                 updateParents(entity, insertions, {});
 
29746             diff.created().forEach(function(entity) {
 
29747                 insertions[entity.id] = entity;
 
29750             rtree.load(_.map(insertions, entityRectangle));
 
29753         return rtree.search(extent.rectangle()).map(function(rect) {
 
29754             return head.entity(rect.id);
 
29760 iD.Way = iD.Entity.way = function iD_Way() {
 
29761     if (!(this instanceof iD_Way)) {
 
29762         return (new iD_Way()).initialize(arguments);
 
29763     } else if (arguments.length) {
 
29764         this.initialize(arguments);
 
29768 iD.Way.prototype = Object.create(iD.Entity.prototype);
 
29770 _.extend(iD.Way.prototype, {
 
29774     copy: function(resolver, copies) {
 
29775         if (copies[this.id])
 
29776             return copies[this.id];
 
29778         var copy = iD.Entity.prototype.copy.call(this, resolver, copies);
 
29780         var nodes = this.nodes.map(function(id) {
 
29781             return resolver.entity(id).copy(resolver, copies).id;
 
29784         copy = copy.update({nodes: nodes});
 
29785         copies[this.id] = copy;
 
29790     extent: function(resolver) {
 
29791         return resolver.transient(this, 'extent', function() {
 
29792             var extent = iD.geo.Extent();
 
29793             for (var i = 0; i < this.nodes.length; i++) {
 
29794                 var node = resolver.hasEntity(this.nodes[i]);
 
29796                     extent._extend(node.extent());
 
29803     first: function() {
 
29804         return this.nodes[0];
 
29808         return this.nodes[this.nodes.length - 1];
 
29811     contains: function(node) {
 
29812         return this.nodes.indexOf(node) >= 0;
 
29815     affix: function(node) {
 
29816         if (this.nodes[0] === node) return 'prefix';
 
29817         if (this.nodes[this.nodes.length - 1] === node) return 'suffix';
 
29820     layer: function() {
 
29821         // explicit layer tag, clamp between -10, 10..
 
29822         if (this.tags.layer !== undefined) {
 
29823             return Math.max(-10, Math.min(+(this.tags.layer), 10));
 
29826         // implied layer tag..
 
29827         if (this.tags.location === 'overground') return 1;
 
29828         if (this.tags.location === 'underground') return -1;
 
29829         if (this.tags.location === 'underwater') return -10;
 
29831         if (this.tags.power === 'line') return 10;
 
29832         if (this.tags.power === 'minor_line') return 10;
 
29833         if (this.tags.aerialway) return 10;
 
29834         if (this.tags.bridge) return 1;
 
29835         if (this.tags.cutting) return -1;
 
29836         if (this.tags.tunnel) return -1;
 
29837         if (this.tags.waterway) return -1;
 
29838         if (this.tags.man_made === 'pipeline') return -10;
 
29839         if (this.tags.boundary) return -10;
 
29843     isOneWay: function() {
 
29844         // explicit oneway tag..
 
29845         if (['yes', '1', '-1'].indexOf(this.tags.oneway) !== -1) { return true; }
 
29846         if (['no', '0'].indexOf(this.tags.oneway) !== -1) { return false; }
 
29848         // implied oneway tag..
 
29849         for (var key in this.tags) {
 
29850             if (key in iD.oneWayTags && (this.tags[key] in iD.oneWayTags[key]))
 
29856     isClosed: function() {
 
29857         return this.nodes.length > 0 && this.first() === this.last();
 
29860     isConvex: function(resolver) {
 
29861         if (!this.isClosed() || this.isDegenerate()) return null;
 
29863         var nodes = _.uniq(resolver.childNodes(this)),
 
29864             coords = _.map(nodes, 'loc'),
 
29865             curr = 0, prev = 0;
 
29867         for (var i = 0; i < coords.length; i++) {
 
29868             var o = coords[(i+1) % coords.length],
 
29870                 b = coords[(i+2) % coords.length],
 
29871                 res = iD.geo.cross(o, a, b);
 
29873             curr = (res > 0) ? 1 : (res < 0) ? -1 : 0;
 
29876             } else if (prev && curr !== prev) {
 
29884     isArea: function() {
 
29885         if (this.tags.area === 'yes')
 
29887         if (!this.isClosed() || this.tags.area === 'no')
 
29889         for (var key in this.tags)
 
29890             if (key in iD.areaKeys && !(this.tags[key] in iD.areaKeys[key]))
 
29895     isDegenerate: function() {
 
29896         return _.uniq(this.nodes).length < (this.isArea() ? 3 : 2);
 
29899     areAdjacent: function(n1, n2) {
 
29900         for (var i = 0; i < this.nodes.length; i++) {
 
29901             if (this.nodes[i] === n1) {
 
29902                 if (this.nodes[i - 1] === n2) return true;
 
29903                 if (this.nodes[i + 1] === n2) return true;
 
29909     geometry: function(graph) {
 
29910         return graph.transient(this, 'geometry', function() {
 
29911             return this.isArea() ? 'area' : 'line';
 
29915     addNode: function(id, index) {
 
29916         var nodes = this.nodes.slice();
 
29917         nodes.splice(index === undefined ? nodes.length : index, 0, id);
 
29918         return this.update({nodes: nodes});
 
29921     updateNode: function(id, index) {
 
29922         var nodes = this.nodes.slice();
 
29923         nodes.splice(index, 1, id);
 
29924         return this.update({nodes: nodes});
 
29927     replaceNode: function(needle, replacement) {
 
29928         if (this.nodes.indexOf(needle) < 0)
 
29931         var nodes = this.nodes.slice();
 
29932         for (var i = 0; i < nodes.length; i++) {
 
29933             if (nodes[i] === needle) {
 
29934                 nodes[i] = replacement;
 
29937         return this.update({nodes: nodes});
 
29940     removeNode: function(id) {
 
29943         for (var i = 0; i < this.nodes.length; i++) {
 
29944             var node = this.nodes[i];
 
29945             if (node !== id && nodes[nodes.length - 1] !== node) {
 
29950         // Preserve circularity
 
29951         if (this.nodes.length > 1 && this.first() === id && this.last() === id && nodes[nodes.length - 1] !== nodes[0]) {
 
29952             nodes.push(nodes[0]);
 
29955         return this.update({nodes: nodes});
 
29958     asJXON: function(changeset_id) {
 
29961                 '@id': this.osmId(),
 
29962                 '@version': this.version || 0,
 
29963                 nd: _.map(this.nodes, function(id) {
 
29964                     return { keyAttributes: { ref: iD.Entity.id.toOSM(id) } };
 
29966                 tag: _.map(this.tags, function(v, k) {
 
29967                     return { keyAttributes: { k: k, v: v } };
 
29971         if (changeset_id) r.way['@changeset'] = changeset_id;
 
29975     asGeoJSON: function(resolver) {
 
29976         return resolver.transient(this, 'GeoJSON', function() {
 
29977             var coordinates = _.map(resolver.childNodes(this), 'loc');
 
29978             if (this.isArea() && this.isClosed()) {
 
29981                     coordinates: [coordinates]
 
29985                     type: 'LineString',
 
29986                     coordinates: coordinates
 
29992     area: function(resolver) {
 
29993         return resolver.transient(this, 'area', function() {
 
29994             var nodes = resolver.childNodes(this);
 
29998                 coordinates: [_.map(nodes, 'loc')]
 
30001             if (!this.isClosed() && nodes.length) {
 
30002                 json.coordinates[0].push(nodes[0].loc);
 
30005             var area = d3.geo.area(json);
 
30007             // Heuristic for detecting counterclockwise winding order. Assumes
 
30008             // that OpenStreetMap polygons are not hemisphere-spanning.
 
30009             if (area > 2 * Math.PI) {
 
30010                 json.coordinates[0] = json.coordinates[0].reverse();
 
30011                 area = d3.geo.area(json);
 
30014             return isNaN(area) ? 0 : area;
 
30018 iD.Background = function(context) {
 
30019     var dispatch = d3.dispatch('change'),
 
30020         baseLayer = iD.TileLayer(context).projection(context.projection),
 
30021         overlayLayers = [],
 
30025     function findSource(id) {
 
30026         return _.find(backgroundSources, function(d) {
 
30027             return d.id && d.id === id;
 
30032     function background(selection) {
 
30033         var base = selection.selectAll('.layer-background')
 
30037             .insert('div', '.layer-data')
 
30038             .attr('class', 'layer layer-background');
 
30040         base.call(baseLayer);
 
30042         var overlays = selection.selectAll('.layer-overlay')
 
30043             .data(overlayLayers, function(d) { return d.source().name(); });
 
30046             .insert('div', '.layer-data')
 
30047             .attr('class', 'layer layer-overlay');
 
30049         overlays.each(function(layer) {
 
30050             d3.select(this).call(layer);
 
30058     background.updateImagery = function() {
 
30059         var b = background.baseLayerSource(),
 
30060             o = overlayLayers.map(function (d) { return d.source().id; }).join(','),
 
30061             meters = iD.geo.offsetToMeters(b.offset()),
 
30063             x = +meters[0].toFixed(2),
 
30064             y = +meters[1].toFixed(2),
 
30065             q = iD.util.stringQs(location.hash.substring(1));
 
30068         if (id === 'custom') {
 
30069             id = 'custom:' + b.template;
 
30075             delete q.background;
 
30084         if (Math.abs(x) > epsilon || Math.abs(y) > epsilon) {
 
30085             q.offset = x + ',' + y;
 
30090         location.replace('#' + iD.util.qsString(q, true));
 
30092         var imageryUsed = [b.imageryUsed()];
 
30094         overlayLayers.forEach(function (d) {
 
30095             var source = d.source();
 
30096             if (!source.isLocatorOverlay()) {
 
30097                 imageryUsed.push(source.imageryUsed());
 
30101         var gpx = context.layers().layer('gpx');
 
30102         if (gpx && gpx.enabled() && gpx.hasGpx()) {
 
30103             imageryUsed.push('Local GPX');
 
30106         var mapillary_images = context.layers().layer('mapillary-images');
 
30107         if (mapillary_images && mapillary_images.enabled()) {
 
30108             imageryUsed.push('Mapillary Images');
 
30111         var mapillary_signs = context.layers().layer('mapillary-signs');
 
30112         if (mapillary_signs && mapillary_signs.enabled()) {
 
30113             imageryUsed.push('Mapillary Signs');
 
30116         context.history().imageryUsed(imageryUsed);
 
30119     background.sources = function(extent) {
 
30120         return backgroundSources.filter(function(source) {
 
30121             return source.intersects(extent);
 
30125     background.dimensions = function(_) {
 
30126         baseLayer.dimensions(_);
 
30128         overlayLayers.forEach(function(layer) {
 
30129             layer.dimensions(_);
 
30133     background.baseLayerSource = function(d) {
 
30134         if (!arguments.length) return baseLayer.source();
 
30135         baseLayer.source(d);
 
30137         background.updateImagery();
 
30141     background.bing = function() {
 
30142         background.baseLayerSource(findSource('Bing'));
 
30145     background.showsLayer = function(d) {
 
30146         return d === baseLayer.source() ||
 
30147             (d.id === 'custom' && baseLayer.source().id === 'custom') ||
 
30148             overlayLayers.some(function(l) { return l.source() === d; });
 
30151     background.overlayLayerSources = function() {
 
30152         return overlayLayers.map(function (l) { return l.source(); });
 
30155     background.toggleOverlayLayer = function(d) {
 
30158         for (var i = 0; i < overlayLayers.length; i++) {
 
30159             layer = overlayLayers[i];
 
30160             if (layer.source() === d) {
 
30161                 overlayLayers.splice(i, 1);
 
30163                 background.updateImagery();
 
30168         layer = iD.TileLayer(context)
 
30170             .projection(context.projection)
 
30171             .dimensions(baseLayer.dimensions());
 
30173         overlayLayers.push(layer);
 
30175         background.updateImagery();
 
30178     background.nudge = function(d, zoom) {
 
30179         baseLayer.source().nudge(d, zoom);
 
30181         background.updateImagery();
 
30185     background.offset = function(d) {
 
30186         if (!arguments.length) return baseLayer.source().offset();
 
30187         baseLayer.source().offset(d);
 
30189         background.updateImagery();
 
30193     background.load = function(imagery) {
 
30194         function parseMap(qmap) {
 
30195             if (!qmap) return false;
 
30196             var args = qmap.split('/').map(Number);
 
30197             if (args.length < 3 || args.some(isNaN)) return false;
 
30198             return iD.geo.Extent([args[1], args[2]]);
 
30201         var q = iD.util.stringQs(location.hash.substring(1)),
 
30202             chosen = q.background || q.layer,
 
30203             extent = parseMap(q.map),
 
30206         backgroundSources = imagery.map(function(source) {
 
30207             if (source.type === 'bing') {
 
30208                 return iD.BackgroundSource.Bing(source, dispatch);
 
30210                 return iD.BackgroundSource(source);
 
30214         backgroundSources.unshift(iD.BackgroundSource.None());
 
30216         if (!chosen && extent) {
 
30217             best = _.find(this.sources(extent), function(s) { return s.best(); });
 
30220         if (chosen && chosen.indexOf('custom:') === 0) {
 
30221             background.baseLayerSource(iD.BackgroundSource.Custom(chosen.replace(/^custom:/, '')));
 
30223             background.baseLayerSource(findSource(chosen) || best || findSource('Bing') || backgroundSources[1] || backgroundSources[0]);
 
30226         var locator = _.find(backgroundSources, function(d) {
 
30227             return d.overlay && d.default;
 
30231             background.toggleOverlayLayer(locator);
 
30234         var overlays = (q.overlays || '').split(',');
 
30235         overlays.forEach(function(overlay) {
 
30236             overlay = findSource(overlay);
 
30238                 background.toggleOverlayLayer(overlay);
 
30243             var gpx = context.layers().layer('gpx');
 
30250             var offset = q.offset.replace(/;/g, ',').split(',').map(function(n) {
 
30251                 return !isNaN(n) && n;
 
30254             if (offset.length === 2) {
 
30255                 background.offset(iD.geo.metersToOffset(offset));
 
30260     return d3.rebind(background, dispatch, 'on');
 
30262 iD.BackgroundSource = function(data) {
 
30263     var source = _.clone(data),
 
30265         name = source.name,
 
30266         best = !!source.best;
 
30268     source.scaleExtent = data.scaleExtent || [0, 20];
 
30269     source.overzoom = data.overzoom !== false;
 
30271     source.offset = function(_) {
 
30272         if (!arguments.length) return offset;
 
30277     source.nudge = function(_, zoomlevel) {
 
30278         offset[0] += _[0] / Math.pow(2, zoomlevel);
 
30279         offset[1] += _[1] / Math.pow(2, zoomlevel);
 
30283     source.name = function() {
 
30287     source.best = function() {
 
30291     source.area = function() {
 
30292         if (!data.polygon) return Number.MAX_VALUE;  // worldwide
 
30293         var area = d3.geo.area({ type: 'MultiPolygon', coordinates: [ data.polygon ] });
 
30294         return isNaN(area) ? 0 : area;
 
30297     source.imageryUsed = function() {
 
30298         return source.id || name;
 
30301     source.url = function(coord) {
 
30302         return data.template
 
30303             .replace('{x}', coord[0])
 
30304             .replace('{y}', coord[1])
 
30305             // TMS-flipped y coordinate
 
30306             .replace(/\{[t-]y\}/, Math.pow(2, coord[2]) - coord[1] - 1)
 
30307             .replace(/\{z(oom)?\}/, coord[2])
 
30308             .replace(/\{switch:([^}]+)\}/, function(s, r) {
 
30309                 var subdomains = r.split(',');
 
30310                 return subdomains[(coord[0] + coord[1]) % subdomains.length];
 
30312             .replace('{u}', function() {
 
30314                 for (var zoom = coord[2]; zoom > 0; zoom--) {
 
30316                     var mask = 1 << (zoom - 1);
 
30317                     if ((coord[0] & mask) !== 0) b++;
 
30318                     if ((coord[1] & mask) !== 0) b += 2;
 
30325     source.intersects = function(extent) {
 
30326         extent = extent.polygon();
 
30327         return !data.polygon || data.polygon.some(function(polygon) {
 
30328             return iD.geo.polygonIntersectsPolygon(polygon, extent, true);
 
30332     source.validZoom = function(z) {
 
30333         return source.scaleExtent[0] <= z &&
 
30334             (source.overzoom || source.scaleExtent[1] > z);
 
30337     source.isLocatorOverlay = function() {
 
30338         return name === 'Locator Overlay';
 
30341     source.copyrightNotices = function() {};
 
30346 iD.BackgroundSource.Bing = function(data, dispatch) {
 
30347     // http://msdn.microsoft.com/en-us/library/ff701716.aspx
 
30348     // http://msdn.microsoft.com/en-us/library/ff701701.aspx
 
30350     data.template = 'https://ecn.t{switch:0,1,2,3}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&mkt=en-gb&n=z';
 
30352     var bing = iD.BackgroundSource(data),
 
30353         key = 'Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU', // Same as P2 and JOSM
 
30354         url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial?include=ImageryProviders&key=' +
 
30355             key + '&jsonp={callback}',
 
30358     d3.jsonp(url, function(json) {
 
30359         providers = json.resourceSets[0].resources[0].imageryProviders.map(function(provider) {
 
30361                 attribution: provider.attribution,
 
30362                 areas: provider.coverageAreas.map(function(area) {
 
30364                         zoom: [area.zoomMin, area.zoomMax],
 
30365                         extent: iD.geo.Extent([area.bbox[1], area.bbox[0]], [area.bbox[3], area.bbox[2]])
 
30373     bing.copyrightNotices = function(zoom, extent) {
 
30374         zoom = Math.min(zoom, 21);
 
30375         return providers.filter(function(provider) {
 
30376             return _.some(provider.areas, function(area) {
 
30377                 return extent.intersects(area.extent) &&
 
30378                     area.zoom[0] <= zoom &&
 
30379                     area.zoom[1] >= zoom;
 
30381         }).map(function(provider) {
 
30382             return provider.attribution;
 
30386     bing.logo = 'bing_maps.png';
 
30387     bing.terms_url = 'https://blog.openstreetmap.org/2010/11/30/microsoft-imagery-details';
 
30392 iD.BackgroundSource.None = function() {
 
30393     var source = iD.BackgroundSource({id: 'none', template: ''});
 
30395     source.name = function() {
 
30396         return t('background.none');
 
30399     source.imageryUsed = function() {
 
30403     source.area = function() {
 
30410 iD.BackgroundSource.Custom = function(template) {
 
30411     var source = iD.BackgroundSource({id: 'custom', template: template});
 
30413     source.name = function() {
 
30414         return t('background.custom');
 
30417     source.imageryUsed = function() {
 
30418         return 'Custom (' + template + ')';
 
30421     source.area = function() {
 
30427 iD.Features = function(context) {
 
30428     var traffic_roads = {
 
30430         'motorway_link': true,
 
30432         'trunk_link': true,
 
30434         'primary_link': true,
 
30436         'secondary_link': true,
 
30438         'tertiary_link': true,
 
30439         'residential': true,
 
30440         'unclassified': true,
 
30441         'living_street': true
 
30444     var service_roads = {
 
30456         'pedestrian': true,
 
30460     var past_futures = {
 
30462         'construction': true,
 
30464         'dismantled': true,
 
30467         'demolished': true,
 
30468         'obliterated': true
 
30471     var dispatch = d3.dispatch('change', 'redraw'),
 
30479     function update() {
 
30480         _hidden = features.hidden();
 
30485     function defineFeature(k, filter, max) {
 
30489             enabled: true,   // whether the user wants it enabled..
 
30491             currentMax: (max || Infinity),
 
30492             defaultMax: (max || Infinity),
 
30493             enable: function() { this.enabled = true; this.currentMax = this.defaultMax; },
 
30494             disable: function() { this.enabled = false; this.currentMax = 0; },
 
30495             hidden: function() { return !context.editable() || this.count > this.currentMax * _cullFactor; },
 
30496             autoHidden: function() { return this.hidden() && this.currentMax > 0; }
 
30501     defineFeature('points', function isPoint(entity, resolver, geometry) {
 
30502         return geometry === 'point';
 
30505     defineFeature('traffic_roads', function isTrafficRoad(entity) {
 
30506         return traffic_roads[entity.tags.highway];
 
30509     defineFeature('service_roads', function isServiceRoad(entity) {
 
30510         return service_roads[entity.tags.highway];
 
30513     defineFeature('paths', function isPath(entity) {
 
30514         return paths[entity.tags.highway];
 
30517     defineFeature('buildings', function isBuilding(entity) {
 
30519             !!entity.tags['building:part'] ||
 
30520             (!!entity.tags.building && entity.tags.building !== 'no') ||
 
30521             entity.tags.amenity === 'shelter' ||
 
30522             entity.tags.parking === 'multi-storey' ||
 
30523             entity.tags.parking === 'sheds' ||
 
30524             entity.tags.parking === 'carports' ||
 
30525             entity.tags.parking === 'garage_boxes'
 
30529     defineFeature('landuse', function isLanduse(entity, resolver, geometry) {
 
30530         return geometry === 'area' &&
 
30531             !_features.buildings.filter(entity) &&
 
30532             !_features.water.filter(entity);
 
30535     defineFeature('boundaries', function isBoundary(entity) {
 
30536         return !!entity.tags.boundary;
 
30539     defineFeature('water', function isWater(entity) {
 
30541             !!entity.tags.waterway ||
 
30542             entity.tags.natural === 'water' ||
 
30543             entity.tags.natural === 'coastline' ||
 
30544             entity.tags.natural === 'bay' ||
 
30545             entity.tags.landuse === 'pond' ||
 
30546             entity.tags.landuse === 'basin' ||
 
30547             entity.tags.landuse === 'reservoir' ||
 
30548             entity.tags.landuse === 'salt_pond'
 
30552     defineFeature('rail', function isRail(entity) {
 
30554             !!entity.tags.railway ||
 
30555             entity.tags.landuse === 'railway'
 
30557             traffic_roads[entity.tags.highway] ||
 
30558             service_roads[entity.tags.highway] ||
 
30559             paths[entity.tags.highway]
 
30563     defineFeature('power', function isPower(entity) {
 
30564         return !!entity.tags.power;
 
30567     // contains a past/future tag, but not in active use as a road/path/cycleway/etc..
 
30568     defineFeature('past_future', function isPastFuture(entity) {
 
30570             traffic_roads[entity.tags.highway] ||
 
30571             service_roads[entity.tags.highway] ||
 
30572             paths[entity.tags.highway]
 
30573         ) { return false; }
 
30575         var strings = Object.keys(entity.tags);
 
30577         for (var i = 0; i < strings.length; i++) {
 
30578             var s = strings[i];
 
30579             if (past_futures[s] || past_futures[entity.tags[s]]) { return true; }
 
30584     // Lines or areas that don't match another feature filter.
 
30585     // IMPORTANT: The 'others' feature must be the last one defined,
 
30586     //   so that code in getMatches can skip this test if `hasMatch = true`
 
30587     defineFeature('others', function isOther(entity, resolver, geometry) {
 
30588         return (geometry === 'line' || geometry === 'area');
 
30592     function features() {}
 
30594     features.features = function() {
 
30598     features.keys = function() {
 
30602     features.enabled = function(k) {
 
30603         if (!arguments.length) {
 
30604             return _.filter(_keys, function(k) { return _features[k].enabled; });
 
30606         return _features[k] && _features[k].enabled;
 
30609     features.disabled = function(k) {
 
30610         if (!arguments.length) {
 
30611             return _.reject(_keys, function(k) { return _features[k].enabled; });
 
30613         return _features[k] && !_features[k].enabled;
 
30616     features.hidden = function(k) {
 
30617         if (!arguments.length) {
 
30618             return _.filter(_keys, function(k) { return _features[k].hidden(); });
 
30620         return _features[k] && _features[k].hidden();
 
30623     features.autoHidden = function(k) {
 
30624         if (!arguments.length) {
 
30625             return _.filter(_keys, function(k) { return _features[k].autoHidden(); });
 
30627         return _features[k] && _features[k].autoHidden();
 
30630     features.enable = function(k) {
 
30631         if (_features[k] && !_features[k].enabled) {
 
30632             _features[k].enable();
 
30637     features.disable = function(k) {
 
30638         if (_features[k] && _features[k].enabled) {
 
30639             _features[k].disable();
 
30644     features.toggle = function(k) {
 
30645         if (_features[k]) {
 
30646             (function(f) { return f.enabled ? f.disable() : f.enable(); }(_features[k]));
 
30651     features.resetStats = function() {
 
30652         _.each(_features, function(f) { f.count = 0; });
 
30656     features.gatherStats = function(d, resolver, dimensions) {
 
30657         var needsRedraw = false,
 
30658             type = _.groupBy(d, function(ent) { return ent.type; }),
 
30659             entities = [].concat(type.relation || [], type.way || [], type.node || []),
 
30660             currHidden, geometry, matches;
 
30662         _.each(_features, function(f) { f.count = 0; });
 
30664         // adjust the threshold for point/building culling based on viewport size..
 
30665         // a _cullFactor of 1 corresponds to a 1000x1000px viewport..
 
30666         _cullFactor = dimensions[0] * dimensions[1] / 1000000;
 
30668         for (var i = 0; i < entities.length; i++) {
 
30669             geometry = entities[i].geometry(resolver);
 
30670             if (!(geometry === 'vertex' || geometry === 'relation')) {
 
30671                 matches = Object.keys(features.getMatches(entities[i], resolver, geometry));
 
30672                 for (var j = 0; j < matches.length; j++) {
 
30673                     _features[matches[j]].count++;
 
30678         currHidden = features.hidden();
 
30679         if (currHidden !== _hidden) {
 
30680             _hidden = currHidden;
 
30681             needsRedraw = true;
 
30685         return needsRedraw;
 
30688     features.stats = function() {
 
30689         _.each(_keys, function(k) { _stats[k] = _features[k].count; });
 
30693     features.clear = function(d) {
 
30694         for (var i = 0; i < d.length; i++) {
 
30695             features.clearEntity(d[i]);
 
30699     features.clearEntity = function(entity) {
 
30700         delete _cache[iD.Entity.key(entity)];
 
30703     features.reset = function() {
 
30707     features.getMatches = function(entity, resolver, geometry) {
 
30708         if (geometry === 'vertex' || geometry === 'relation') return {};
 
30710         var ent = iD.Entity.key(entity);
 
30711         if (!_cache[ent]) {
 
30715         if (!_cache[ent].matches) {
 
30719             for (var i = 0; i < _keys.length; i++) {
 
30720                 if (_keys[i] === 'others') {
 
30721                     if (hasMatch) continue;
 
30723                     // Multipolygon members:
 
30725                     //   1. is a way that hasn't matched other "interesting" feature rules,
 
30726                     //   2. and it belongs to a single parent multipolygon relation
 
30727                     // ...then match whatever feature rules the parent multipolygon has matched.
 
30728                     // see #2548, #2887
 
30731                     // For this to work, getMatches must be called on relations before ways.
 
30733                     if (entity.type === 'way') {
 
30734                         var parents = features.getParents(entity, resolver, geometry);
 
30735                         if (parents.length === 1 && parents[0].isMultipolygon()) {
 
30736                             var pkey = iD.Entity.key(parents[0]);
 
30737                             if (_cache[pkey] && _cache[pkey].matches) {
 
30738                                 matches = _.clone(_cache[pkey].matches);
 
30745                 if (_features[_keys[i]].filter(entity, resolver, geometry)) {
 
30746                     matches[_keys[i]] = hasMatch = true;
 
30749             _cache[ent].matches = matches;
 
30752         return _cache[ent].matches;
 
30755     features.getParents = function(entity, resolver, geometry) {
 
30756         if (geometry === 'point') return [];
 
30758         var ent = iD.Entity.key(entity);
 
30759         if (!_cache[ent]) {
 
30763         if (!_cache[ent].parents) {
 
30765             if (geometry === 'vertex') {
 
30766                 parents = resolver.parentWays(entity);
 
30767             } else {   // 'line', 'area', 'relation'
 
30768                 parents = resolver.parentRelations(entity);
 
30770             _cache[ent].parents = parents;
 
30772         return _cache[ent].parents;
 
30775     features.isHiddenFeature = function(entity, resolver, geometry) {
 
30776         if (!_hidden.length) return false;
 
30777         if (!entity.version) return false;
 
30779         var matches = features.getMatches(entity, resolver, geometry);
 
30781         for (var i = 0; i < _hidden.length; i++) {
 
30782             if (matches[_hidden[i]]) return true;
 
30787     features.isHiddenChild = function(entity, resolver, geometry) {
 
30788         if (!_hidden.length) return false;
 
30789         if (!entity.version || geometry === 'point') return false;
 
30791         var parents = features.getParents(entity, resolver, geometry);
 
30792         if (!parents.length) return false;
 
30794         for (var i = 0; i < parents.length; i++) {
 
30795             if (!features.isHidden(parents[i], resolver, parents[i].geometry(resolver))) {
 
30802     features.hasHiddenConnections = function(entity, resolver) {
 
30803         if (!_hidden.length) return false;
 
30804         var childNodes, connections;
 
30806         if (entity.type === 'midpoint') {
 
30807             childNodes = [resolver.entity(entity.edge[0]), resolver.entity(entity.edge[1])];
 
30810             childNodes = entity.nodes ? resolver.childNodes(entity) : [];
 
30811             connections = features.getParents(entity, resolver, entity.geometry(resolver));
 
30814         // gather ways connected to child nodes..
 
30815         connections = _.reduce(childNodes, function(result, e) {
 
30816             return resolver.isShared(e) ? _.union(result, resolver.parentWays(e)) : result;
 
30819         return connections.length ? _.some(connections, function(e) {
 
30820             return features.isHidden(e, resolver, e.geometry(resolver));
 
30824     features.isHidden = function(entity, resolver, geometry) {
 
30825         if (!_hidden.length) return false;
 
30826         if (!entity.version) return false;
 
30828         var fn = (geometry === 'vertex' ? features.isHiddenChild : features.isHiddenFeature);
 
30829         return fn(entity, resolver, geometry);
 
30832     features.filter = function(d, resolver) {
 
30833         if (!_hidden.length) return d;
 
30836         for (var i = 0; i < d.length; i++) {
 
30838             if (!features.isHidden(entity, resolver, entity.geometry(resolver))) {
 
30839                 result.push(entity);
 
30845     return d3.rebind(features, dispatch, 'on');
 
30847 iD.Map = function(context) {
 
30848     var dimensions = [1, 1],
 
30849         dispatch = d3.dispatch('move', 'drawn'),
 
30850         projection = context.projection,
 
30851         zoom = d3.behavior.zoom()
 
30852             .translate(projection.translate())
 
30853             .scale(projection.scale() * 2 * Math.PI)
 
30854             .scaleExtent([1024, 256 * Math.pow(2, 24)])
 
30855             .on('zoom', zoomPan),
 
30856         dblclickEnabled = true,
 
30857         redrawEnabled = true,
 
30859         transformed = false,
 
30862         drawLayers = iD.svg.Layers(projection, context),
 
30863         drawPoints = iD.svg.Points(projection, context),
 
30864         drawVertices = iD.svg.Vertices(projection, context),
 
30865         drawLines = iD.svg.Lines(projection),
 
30866         drawAreas = iD.svg.Areas(projection),
 
30867         drawMidpoints = iD.svg.Midpoints(projection, context),
 
30868         drawLabels = iD.svg.Labels(projection, context),
 
30875     function map(selection) {
 
30877             .on('change.map', redraw);
 
30879             .on('change.map', redraw);
 
30880         context.background()
 
30881             .on('change.map', redraw);
 
30883             .on('redraw.map', redraw);
 
30885             .on('change.map', function() {
 
30886                 context.background().updateImagery();
 
30891             .on('dblclick.map', dblClick)
 
30894         supersurface = selection.append('div')
 
30895             .attr('id', 'supersurface')
 
30896             .call(iD.util.setTransform, 0, 0);
 
30898         // Need a wrapper div because Opera can't cope with an absolutely positioned
 
30899         // SVG element: http://bl.ocks.org/jfirebaugh/6fbfbd922552bf776c16
 
30900         wrapper = supersurface
 
30902             .attr('class', 'layer layer-data');
 
30904         map.surface = surface = wrapper
 
30906             .selectAll('.surface')
 
30907             .attr('id', 'surface');
 
30910             .on('mousedown.zoom', function() {
 
30911                 if (d3.event.button === 2) {
 
30912                     d3.event.stopPropagation();
 
30915             .on('mouseup.zoom', function() {
 
30916                 if (resetTransform()) redraw();
 
30918             .on('mousemove.map', function() {
 
30919                 mousemove = d3.event;
 
30921             .on('mouseover.vertices', function() {
 
30922                 if (map.editable() && !transformed) {
 
30923                     var hover = d3.event.target.__data__;
 
30924                     surface.call(drawVertices.drawHover, context.graph(), hover, map.extent(), map.zoom());
 
30925                     dispatch.drawn({full: false});
 
30928             .on('mouseout.vertices', function() {
 
30929                 if (map.editable() && !transformed) {
 
30930                     var hover = d3.event.relatedTarget && d3.event.relatedTarget.__data__;
 
30931                     surface.call(drawVertices.drawHover, context.graph(), hover, map.extent(), map.zoom());
 
30932                     dispatch.drawn({full: false});
 
30938             .call(context.background());
 
30941         context.on('enter.map', function() {
 
30942             if (map.editable() && !transformed) {
 
30943                 var all = context.intersects(map.extent()),
 
30944                     filter = d3.functor(true),
 
30945                     graph = context.graph();
 
30947                 all = context.features().filter(all, graph);
 
30949                     .call(drawVertices, graph, all, filter, map.extent(), map.zoom())
 
30950                     .call(drawMidpoints, graph, all, filter, map.trimmedExtent());
 
30951                 dispatch.drawn({full: false});
 
30955         map.dimensions(selection.dimensions());
 
30957         drawLabels.supersurface(supersurface);
 
30960     function pxCenter() {
 
30961         return [dimensions[0] / 2, dimensions[1] / 2];
 
30964     function drawVector(difference, extent) {
 
30965         var graph = context.graph(),
 
30966             features = context.features(),
 
30967             all = context.intersects(map.extent()),
 
30971             var complete = difference.complete(map.extent());
 
30972             data = _.compact(_.values(complete));
 
30973             filter = function(d) { return d.id in complete; };
 
30974             features.clear(data);
 
30977             // force a full redraw if gatherStats detects that a feature
 
30978             // should be auto-hidden (e.g. points or buildings)..
 
30979             if (features.gatherStats(all, graph, dimensions)) {
 
30980                 extent = undefined;
 
30984                 data = context.intersects(map.extent().intersection(extent));
 
30985                 var set = d3.set(_.map(data, 'id'));
 
30986                 filter = function(d) { return set.has(d.id); };
 
30990                 filter = d3.functor(true);
 
30994         data = features.filter(data, graph);
 
30997             .call(drawVertices, graph, data, filter, map.extent(), map.zoom())
 
30998             .call(drawLines, graph, data, filter)
 
30999             .call(drawAreas, graph, data, filter)
 
31000             .call(drawMidpoints, graph, data, filter, map.trimmedExtent())
 
31001             .call(drawLabels, graph, data, filter, dimensions, !difference && !extent)
 
31002             .call(drawPoints, graph, data, filter);
 
31004         dispatch.drawn({full: true});
 
31007     function editOff() {
 
31008         context.features().resetStats();
 
31009         surface.selectAll('.layer-osm *').remove();
 
31010         dispatch.drawn({full: true});
 
31013     function dblClick() {
 
31014         if (!dblclickEnabled) {
 
31015             d3.event.preventDefault();
 
31016             d3.event.stopImmediatePropagation();
 
31020     function zoomPan() {
 
31021         if (Math.log(d3.event.scale) / Math.LN2 - 8 < minzoom) {
 
31022             surface.interrupt();
 
31023             iD.ui.flash(context.container())
 
31024                 .select('.content')
 
31025                 .text(t('cannot_zoom'));
 
31026             setZoom(context.minEditableZoom(), true);
 
31028             dispatch.move(map);
 
31033             .translate(d3.event.translate)
 
31034             .scale(d3.event.scale / (2 * Math.PI));
 
31036         var scale = d3.event.scale / transformStart[0],
 
31037             tX = (d3.event.translate[0] / scale - transformStart[1][0]) * scale,
 
31038             tY = (d3.event.translate[1] / scale - transformStart[1][1]) * scale;
 
31040         transformed = true;
 
31041         iD.util.setTransform(supersurface, tX, tY, scale);
 
31044         dispatch.move(map);
 
31047     function resetTransform() {
 
31048         if (!transformed) return false;
 
31050         surface.selectAll('.radial-menu').interrupt().remove();
 
31051         iD.util.setTransform(supersurface, 0, 0);
 
31052         transformed = false;
 
31056     function redraw(difference, extent) {
 
31057         if (!surface || !redrawEnabled) return;
 
31059         clearTimeout(timeoutId);
 
31061         // If we are in the middle of a zoom/pan, we can't do differenced redraws.
 
31062         // It would result in artifacts where differenced entities are redrawn with
 
31063         // one transform and unchanged entities with another.
 
31064         if (resetTransform()) {
 
31065             difference = extent = undefined;
 
31068         var zoom = String(~~map.zoom());
 
31069         if (surface.attr('data-zoom') !== zoom) {
 
31070             surface.attr('data-zoom', zoom)
 
31071                 .classed('low-zoom', zoom <= 16);
 
31075             supersurface.call(context.background());
 
31079         if (map.editable()) {
 
31080             context.loadTiles(projection, dimensions);
 
31081             drawVector(difference, extent);
 
31090             projection.scale() * 2 * Math.PI,
 
31091             projection.translate().slice()];
 
31097     function queueRedraw() {
 
31098         timeoutId = setTimeout(function() { redraw(); }, 750);
 
31101     function pointLocation(p) {
 
31102         var translate = projection.translate(),
 
31103             scale = projection.scale() * 2 * Math.PI;
 
31104         return [(p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale];
 
31107     function locationPoint(l) {
 
31108         var translate = projection.translate(),
 
31109             scale = projection.scale() * 2 * Math.PI;
 
31110         return [l[0] * scale + translate[0], l[1] * scale + translate[1]];
 
31113     map.mouse = function() {
 
31114         var e = mousemove || d3.event, s;
 
31115         while ((s = e.sourceEvent)) e = s;
 
31119     map.mouseCoordinates = function() {
 
31120         return projection.invert(map.mouse());
 
31123     map.dblclickEnable = function(_) {
 
31124         if (!arguments.length) return dblclickEnabled;
 
31125         dblclickEnabled = _;
 
31129     map.redrawEnable = function(_) {
 
31130         if (!arguments.length) return redrawEnabled;
 
31135     function interpolateZoom(_) {
 
31136         var k = projection.scale(),
 
31137             t = projection.translate();
 
31139         surface.node().__chart__ = {
 
31146         projection.scale(k).translate(t);  // undo setZoom projection changes
 
31148         zoom.event(surface.transition());
 
31151     function setZoom(_, force) {
 
31152         if (_ === map.zoom() && !force)
 
31154         var scale = 256 * Math.pow(2, _),
 
31155             center = pxCenter(),
 
31156             l = pointLocation(center);
 
31157         scale = Math.max(1024, Math.min(256 * Math.pow(2, 24), scale));
 
31158         projection.scale(scale / (2 * Math.PI));
 
31160         var t = projection.translate();
 
31161         l = locationPoint(l);
 
31162         t[0] += center[0] - l[0];
 
31163         t[1] += center[1] - l[1];
 
31164         projection.translate(t);
 
31165         zoom.translate(projection.translate());
 
31169     function setCenter(_) {
 
31170         var c = map.center();
 
31171         if (_[0] === c[0] && _[1] === c[1])
 
31173         var t = projection.translate(),
 
31175             ll = projection(_);
 
31176         projection.translate([
 
31177             t[0] - ll[0] + pxC[0],
 
31178             t[1] - ll[1] + pxC[1]]);
 
31179         zoom.translate(projection.translate());
 
31183     map.pan = function(d) {
 
31184         var t = projection.translate();
 
31187         projection.translate(t);
 
31188         zoom.translate(projection.translate());
 
31189         dispatch.move(map);
 
31193     map.dimensions = function(_) {
 
31194         if (!arguments.length) return dimensions;
 
31195         var center = map.center();
 
31197         drawLayers.dimensions(dimensions);
 
31198         context.background().dimensions(dimensions);
 
31199         projection.clipExtent([[0, 0], dimensions]);
 
31200         mouse = iD.util.fastMouse(supersurface.node());
 
31205     function zoomIn(integer) {
 
31206       interpolateZoom(~~map.zoom() + integer);
 
31209     function zoomOut(integer) {
 
31210       interpolateZoom(~~map.zoom() - integer);
 
31213     map.zoomIn = function() { zoomIn(1); };
 
31214     map.zoomInFurther = function() { zoomIn(4); };
 
31216     map.zoomOut = function() { zoomOut(1); };
 
31217     map.zoomOutFurther = function() { zoomOut(4); };
 
31219     map.center = function(loc) {
 
31220         if (!arguments.length) {
 
31221             return projection.invert(pxCenter());
 
31224         if (setCenter(loc)) {
 
31225             dispatch.move(map);
 
31231     map.zoom = function(z) {
 
31232         if (!arguments.length) {
 
31233             return Math.max(Math.log(projection.scale() * 2 * Math.PI) / Math.LN2 - 8, 0);
 
31237             surface.interrupt();
 
31238             iD.ui.flash(context.container())
 
31239                 .select('.content')
 
31240                 .text(t('cannot_zoom'));
 
31241             z = context.minEditableZoom();
 
31245             dispatch.move(map);
 
31251     map.zoomTo = function(entity, zoomLimits) {
 
31252         var extent = entity.extent(context.graph());
 
31253         if (!isFinite(extent.area())) return;
 
31255         var zoom = map.trimmedExtentZoom(extent);
 
31256         zoomLimits = zoomLimits || [context.minEditableZoom(), 20];
 
31257         map.centerZoom(extent.center(), Math.min(Math.max(zoom, zoomLimits[0]), zoomLimits[1]));
 
31260     map.centerZoom = function(loc, z) {
 
31261         var centered = setCenter(loc),
 
31262             zoomed   = setZoom(z);
 
31264         if (centered || zoomed) {
 
31265             dispatch.move(map);
 
31271     map.centerEase = function(loc2, duration) {
 
31272         duration = duration || 250;
 
31274         surface.one('mousedown.ease', function() {
 
31282         var t1 = Date.now(),
 
31283             t2 = t1 + duration,
 
31284             loc1 = map.center(),
 
31285             ease = d3.ease('cubic-in-out');
 
31289         d3.timer(function() {
 
31290             if (!easing) return true;  // cancelled ease
 
31292             var tNow = Date.now();
 
31298             var locNow = iD.geo.interp(loc1, loc2, ease((tNow - t1) / duration));
 
31302                 scale: zoom.scale(),
 
31303                 translate: zoom.translate()
 
31313     map.cancelEase = function() {
 
31319     map.extent = function(_) {
 
31320         if (!arguments.length) {
 
31321             return new iD.geo.Extent(projection.invert([0, dimensions[1]]),
 
31322                                  projection.invert([dimensions[0], 0]));
 
31324             var extent = iD.geo.Extent(_);
 
31325             map.centerZoom(extent.center(), map.extentZoom(extent));
 
31329     map.trimmedExtent = function(_) {
 
31330         if (!arguments.length) {
 
31331             var headerY = 60, footerY = 30, pad = 10;
 
31332             return new iD.geo.Extent(projection.invert([pad, dimensions[1] - footerY - pad]),
 
31333                     projection.invert([dimensions[0] - pad, headerY + pad]));
 
31335             var extent = iD.geo.Extent(_);
 
31336             map.centerZoom(extent.center(), map.trimmedExtentZoom(extent));
 
31340     function calcZoom(extent, dim) {
 
31341         var tl = projection([extent[0][0], extent[1][1]]),
 
31342             br = projection([extent[1][0], extent[0][1]]);
 
31344         // Calculate maximum zoom that fits extent
 
31345         var hFactor = (br[0] - tl[0]) / dim[0],
 
31346             vFactor = (br[1] - tl[1]) / dim[1],
 
31347             hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2,
 
31348             vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2,
 
31349             newZoom = map.zoom() - Math.max(hZoomDiff, vZoomDiff);
 
31354     map.extentZoom = function(_) {
 
31355         return calcZoom(iD.geo.Extent(_), dimensions);
 
31358     map.trimmedExtentZoom = function(_) {
 
31359         var trimY = 120, trimX = 40,
 
31360             trimmed = [dimensions[0] - trimX, dimensions[1] - trimY];
 
31361         return calcZoom(iD.geo.Extent(_), trimmed);
 
31364     map.editable = function() {
 
31365         return map.zoom() >= context.minEditableZoom();
 
31368     map.minzoom = function(_) {
 
31369         if (!arguments.length) return minzoom;
 
31374     map.layers = drawLayers;
 
31376     return d3.rebind(map, dispatch, 'on');
 
31378 iD.TileLayer = function(context) {
 
31379     var tileSize = 256,
 
31380         tile = d3.geo.tile(),
 
31385         transformProp = iD.util.prefixCSSProperty('Transform'),
 
31386         source = d3.functor('');
 
31389     // blacklist overlay tiles around Null Island..
 
31390     function nearNullIsland(x, y, z) {
 
31392             var center = Math.pow(2, z - 1),
 
31393                 width = Math.pow(2, z - 6),
 
31394                 min = center - (width / 2),
 
31395                 max = center + (width / 2) - 1;
 
31396             return x >= min && x <= max && y >= min && y <= max;
 
31401     function tileSizeAtZoom(d, z) {
 
31402         var epsilon = 0.002;
 
31403         return ((tileSize * Math.pow(2, z - d[2])) / tileSize) + epsilon;
 
31406     function atZoom(t, distance) {
 
31407         var power = Math.pow(2, distance);
 
31409             Math.floor(t[0] * power),
 
31410             Math.floor(t[1] * power),
 
31414     function lookUp(d) {
 
31415         for (var up = -1; up > -d[2]; up--) {
 
31416             var tile = atZoom(d, up);
 
31417             if (cache[source.url(tile)] !== false) {
 
31423     function uniqueBy(a, n) {
 
31424         var o = [], seen = {};
 
31425         for (var i = 0; i < a.length; i++) {
 
31426             if (seen[a[i][n]] === undefined) {
 
31428                 seen[a[i][n]] = true;
 
31434     function addSource(d) {
 
31435         d.push(source.url(d));
 
31439     // Update tiles based on current state of `projection`.
 
31440     function background(selection) {
 
31441         tile.scale(projection.scale() * 2 * Math.PI)
 
31442             .translate(projection.translate());
 
31445             projection.scale() * Math.PI - projection.translate()[0],
 
31446             projection.scale() * Math.PI - projection.translate()[1]];
 
31448         z = Math.max(Math.log(projection.scale() * 2 * Math.PI) / Math.log(2) - 8, 0);
 
31453     // Derive the tiles onscreen, remove those offscreen and position them.
 
31454     // Important that this part not depend on `projection` because it's
 
31455     // rentered when tiles load/error (see #644).
 
31456     function render(selection) {
 
31458         var showDebug = context.getDebug('tile') && !source.overlay;
 
31460         if (source.validZoom(z)) {
 
31461             tile().forEach(function(d) {
 
31463                 if (d[3] === '') return;
 
31464                 if (typeof d[3] !== 'string') return; // Workaround for chrome crash https://github.com/openstreetmap/iD/issues/2295
 
31466                 if (cache[d[3]] === false && lookUp(d)) {
 
31467                     requests.push(addSource(lookUp(d)));
 
31471             requests = uniqueBy(requests, 3).filter(function(r) {
 
31472                 if (!!source.overlay && nearNullIsland(r[0], r[1], r[2])) {
 
31475                 // don't re-request tiles which have failed in the past
 
31476                 return cache[r[3]] !== false;
 
31480         var pixelOffset = [
 
31481             source.offset()[0] * Math.pow(2, z),
 
31482             source.offset()[1] * Math.pow(2, z)
 
31486             cache[d[3]] = true;
 
31490                 .classed('tile-loaded', true);
 
31494         function error(d) {
 
31495             cache[d[3]] = false;
 
31503         function imageTransform(d) {
 
31504             var _ts = tileSize * Math.pow(2, z - d[2]);
 
31505             var scale = tileSizeAtZoom(d, z);
 
31506             return 'translate(' +
 
31507                 ((d[0] * _ts) - tileOrigin[0] + pixelOffset[0]) + 'px,' +
 
31508                 ((d[1] * _ts) - tileOrigin[1] + pixelOffset[1]) + 'px)' +
 
31509                 'scale(' + scale + ',' + scale + ')';
 
31512         function debugTransform(d) {
 
31513             var _ts = tileSize * Math.pow(2, z - d[2]);
 
31514             var scale = tileSizeAtZoom(d, z);
 
31515             return 'translate(' +
 
31516                 ((d[0] * _ts) - tileOrigin[0] + pixelOffset[0] + scale * (tileSize / 4)) + 'px,' +
 
31517                 ((d[1] * _ts) - tileOrigin[1] + pixelOffset[1] + scale * (tileSize / 2)) + 'px)';
 
31520         var image = selection
 
31522             .data(requests, function(d) { return d[3]; });
 
31525             .style(transformProp, imageTransform)
 
31526             .classed('tile-removing', true)
 
31528                 var tile = d3.select(this);
 
31529                 window.setTimeout(function() {
 
31530                     if (tile.classed('tile-removing')) {
 
31536         image.enter().append('img')
 
31537             .attr('class', 'tile')
 
31538             .attr('src', function(d) { return d[3]; })
 
31539             .on('error', error)
 
31543             .style(transformProp, imageTransform)
 
31544             .classed('tile-debug', showDebug)
 
31545             .classed('tile-removing', false);
 
31548         var debug = selection.selectAll('.tile-label-debug')
 
31549             .data(showDebug ? requests : [], function(d) { return d[3]; });
 
31556             .attr('class', 'tile-label-debug');
 
31559             .text(function(d) { return d[2] + ' / ' + d[0] + ' / ' + d[1]; })
 
31560             .style(transformProp, debugTransform);
 
31563     background.projection = function(_) {
 
31564         if (!arguments.length) return projection;
 
31569     background.dimensions = function(_) {
 
31570         if (!arguments.length) return tile.size();
 
31575     background.source = function(_) {
 
31576         if (!arguments.length) return source;
 
31579         tile.scaleExtent(source.scaleExtent);
 
31586     PointTransform: function(projection) {
 
31587         return function(entity) {
 
31588             // http://jsperf.com/short-array-join
 
31589             var pt = projection(entity.loc);
 
31590             return 'translate(' + pt[0] + ',' + pt[1] + ')';
 
31594     Path: function(projection, graph, polygon) {
 
31596             clip = d3.geo.clipExtent().extent(projection.clipExtent()).stream,
 
31597             project = projection.stream,
 
31598             path = d3.geo.path()
 
31599                 .projection({stream: function(output) { return polygon ? project(output) : project(clip(output)); }});
 
31601         return function(entity) {
 
31602             if (entity.id in cache) {
 
31603                 return cache[entity.id];
 
31605                 return cache[entity.id] = path(entity.asGeoJSON(graph));
 
31610     OneWaySegments: function(projection, graph, dt) {
 
31611         return function(entity) {
 
31617                 clip = d3.geo.clipExtent().extent(projection.clipExtent()).stream,
 
31618                 coordinates = graph.childNodes(entity).map(function(n) {
 
31622             if (entity.tags.oneway === '-1') coordinates.reverse();
 
31625                 type: 'LineString',
 
31626                 coordinates: coordinates
 
31627             }, projection.stream(clip({
 
31628                 lineStart: function() {},
 
31629                 lineEnd: function() {
 
31632                 point: function(x, y) {
 
31636                         var span = iD.geo.euclideanDistance(a, b) - offset;
 
31639                             var angle = Math.atan2(b[1] - a[1], b[0] - a[0]),
 
31640                                 dx = dt * Math.cos(angle),
 
31641                                 dy = dt * Math.sin(angle),
 
31642                                 p = [a[0] + offset * Math.cos(angle),
 
31643                                      a[1] + offset * Math.sin(angle)];
 
31645                             var segment = 'M' + a[0] + ',' + a[1] +
 
31646                                           'L' + p[0] + ',' + p[1];
 
31648                             for (span -= dt; span >= 0; span -= dt) {
 
31651                                 segment += 'L' + p[0] + ',' + p[1];
 
31654                             segment += 'L' + b[0] + ',' + b[1];
 
31655                             segments.push({id: entity.id, index: i, d: segment});
 
31670     RelationMemberTags: function(graph) {
 
31671         return function(entity) {
 
31672             var tags = entity.tags;
 
31673             graph.parentRelations(entity).forEach(function(relation) {
 
31674                 var type = relation.tags.type;
 
31675                 if (type === 'multipolygon' || type === 'boundary') {
 
31676                     tags = _.extend({}, relation.tags, tags);
 
31683 iD.svg.Areas = function(projection) {
 
31684     // Patterns only work in Firefox when set directly on element.
 
31685     // (This is not a bug: https://bugzilla.mozilla.org/show_bug.cgi?id=750632)
 
31687         wetland: 'wetland',
 
31690         construction: 'construction',
 
31691         military: 'construction',
 
31692         cemetery: 'cemetery',
 
31693         grave_yard: 'cemetery',
 
31696         farmland: 'farmland',
 
31700     var patternKeys = ['landuse', 'natural', 'amenity'];
 
31702     function setPattern(d) {
 
31703         for (var i = 0; i < patternKeys.length; i++) {
 
31704             if (patterns.hasOwnProperty(d.tags[patternKeys[i]])) {
 
31705                 this.style.fill = this.style.stroke = 'url("#pattern-' + patterns[d.tags[patternKeys[i]]] + '")';
 
31709         this.style.fill = this.style.stroke = '';
 
31712     return function drawAreas(surface, graph, entities, filter) {
 
31713         var path = iD.svg.Path(projection, graph, true),
 
31717         for (var i = 0; i < entities.length; i++) {
 
31718             var entity = entities[i];
 
31719             if (entity.geometry(graph) !== 'area') continue;
 
31721             multipolygon = iD.geo.isSimpleMultipolygonOuterMember(entity, graph);
 
31722             if (multipolygon) {
 
31723                 areas[multipolygon.id] = {
 
31724                     entity: multipolygon.mergeTags(entity.tags),
 
31725                     area: Math.abs(entity.area(graph))
 
31727             } else if (!areas[entity.id]) {
 
31728                 areas[entity.id] = {
 
31730                     area: Math.abs(entity.area(graph))
 
31735         areas = d3.values(areas).filter(function hasPath(a) { return path(a.entity); });
 
31736         areas.sort(function areaSort(a, b) { return b.area - a.area; });
 
31737         areas = _.map(areas, 'entity');
 
31739         var strokes = areas.filter(function(area) {
 
31740             return area.type === 'way';
 
31750         var clipPaths = surface.selectAll('defs').selectAll('.clipPath')
 
31752            .data(data.clip, iD.Entity.key);
 
31755            .append('clipPath')
 
31756            .attr('class', 'clipPath')
 
31757            .attr('id', function(entity) { return entity.id + '-clippath'; })
 
31760         clipPaths.selectAll('path')
 
31766         var areagroup = surface
 
31767             .selectAll('.layer-areas')
 
31768             .selectAll('g.areagroup')
 
31769             .data(['fill', 'shadow', 'stroke']);
 
31773             .attr('class', function(d) { return 'layer areagroup area-' + d; });
 
31775         var paths = areagroup
 
31778             .data(function(layer) { return data[layer]; }, iD.Entity.key);
 
31780         // Remove exiting areas first, so they aren't included in the `fills`
 
31781         // array used for sorting below (https://github.com/openstreetmap/iD/issues/1903).
 
31785         var fills = surface.selectAll('.area-fill path.area')[0];
 
31787         var bisect = d3.bisector(function(node) {
 
31788             return -node.__data__.area(graph);
 
31791         function sortedByArea(entity) {
 
31792             if (this.__data__ === 'fill') {
 
31793                 return fills[bisect(fills, -entity.area(graph))];
 
31798             .insert('path', sortedByArea)
 
31799             .each(function(entity) {
 
31800                 var layer = this.parentNode.__data__;
 
31802                 this.setAttribute('class', entity.type + ' area ' + layer + ' ' + entity.id);
 
31804                 if (layer === 'fill') {
 
31805                     this.setAttribute('clip-path', 'url(#' + entity.id + '-clippath)');
 
31806                     setPattern.apply(this, arguments);
 
31809             .call(iD.svg.TagClasses());
 
31815 iD.svg.Debug = function(projection, context) {
 
31817     function multipolygons(imagery) {
 
31818         return imagery.map(function(data) {
 
31820                 type: 'MultiPolygon',
 
31821                 coordinates: [ data.polygon ]
 
31826     function drawDebug(surface) {
 
31827         var showsTile = context.getDebug('tile'),
 
31828             showsCollision = context.getDebug('collision'),
 
31829             showsImagery = context.getDebug('imagery'),
 
31830             showsImperial = context.getDebug('imperial'),
 
31831             showsDriveLeft = context.getDebug('driveLeft'),
 
31832             path = d3.geo.path().projection(projection);
 
31835         var debugData = [];
 
31837             debugData.push({ class: 'red', label: 'tile' });
 
31839         if (showsCollision) {
 
31840             debugData.push({ class: 'yellow', label: 'collision' });
 
31842         if (showsImagery) {
 
31843             debugData.push({ class: 'orange', label: 'imagery' });
 
31845         if (showsImperial) {
 
31846             debugData.push({ class: 'cyan', label: 'imperial' });
 
31848         if (showsDriveLeft) {
 
31849             debugData.push({ class: 'green', label: 'driveLeft' });
 
31853         var legend = d3.select('#content')
 
31854             .selectAll('.debug-legend')
 
31855             .data(debugData.length ? [0] : []);
 
31859             .attr('class', 'fillD debug-legend');
 
31865         var legendItems = legend.selectAll('.debug-legend-item')
 
31866             .data(debugData, function(d) { return d.label; });
 
31868         legendItems.enter()
 
31870             .attr('class', function(d) { return 'debug-legend-item ' + d.class; })
 
31871             .text(function(d) { return d.label; });
 
31877         var layer = surface.selectAll('.layer-debug')
 
31878             .data(showsImagery || showsImperial || showsDriveLeft ? [0] : []);
 
31882             .attr('class', 'layer-debug');
 
31888         var extent = context.map().extent(),
 
31889             availableImagery = showsImagery && multipolygons(iD.data.imagery.filter(function(source) {
 
31890                 if (!source.polygon) return false;
 
31891                 return source.polygon.some(function(polygon) {
 
31892                     return iD.geo.polygonIntersectsPolygon(polygon, extent, true);
 
31896         var imagery = layer.selectAll('path.debug-imagery')
 
31897             .data(showsImagery ? availableImagery : []);
 
31901             .attr('class', 'debug-imagery debug orange');
 
31907         var imperial = layer
 
31908             .selectAll('path.debug-imperial')
 
31909             .data(showsImperial ? [iD.data.imperial] : []);
 
31913             .attr('class', 'debug-imperial debug cyan');
 
31919         var driveLeft = layer
 
31920             .selectAll('path.debug-drive-left')
 
31921             .data(showsDriveLeft ? [iD.data.driveLeft] : []);
 
31925             .attr('class', 'debug-drive-left debug green');
 
31932         layer.selectAll('path')
 
31936     // This looks strange because `enabled` methods on other layers are
 
31937     // chainable getter/setters, and this one is just a getter.
 
31938     drawDebug.enabled = function() {
 
31939         if (!arguments.length) {
 
31940             return context.getDebug('tile') ||
 
31941                 context.getDebug('collision') ||
 
31942                 context.getDebug('imagery') ||
 
31943                 context.getDebug('imperial') ||
 
31944                 context.getDebug('driveLeft');
 
31953     A standalone SVG element that contains only a `defs` sub-element. To be
 
31954     used once globally, since defs IDs must be unique within a document.
 
31956 iD.svg.Defs = function(context) {
 
31958     function SVGSpriteDefinition(id, href) {
 
31959         return function(defs) {
 
31960             d3.xml(href, 'image/svg+xml', function(err, svg) {
 
31962                 defs.node().appendChild(
 
31963                     d3.select(svg.documentElement).attr('id', id).node()
 
31969     return function drawDefs(selection) {
 
31970         var defs = selection.append('defs');
 
31973         defs.append('marker')
 
31975                 id: 'oneway-marker',
 
31976                 viewBox: '0 0 10 10',
 
31981                 markerUnits: 'strokeWidth',
 
31985             .attr('class', 'oneway')
 
31986             .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')
 
31987             .attr('stroke', 'none')
 
31988             .attr('fill', '#000')
 
31989             .attr('opacity', '0.5');
 
31992         var patterns = defs.selectAll('pattern')
 
31994                 // pattern name, pattern image name
 
31995                 ['wetland', 'wetland'],
 
31996                 ['construction', 'construction'],
 
31997                 ['cemetery', 'cemetery'],
 
31998                 ['orchard', 'orchard'],
 
31999                 ['farmland', 'farmland'],
 
32008                     return 'pattern-' + d[0];
 
32012                 patternUnits: 'userSpaceOnUse'
 
32015         patterns.append('rect')
 
32021                 'class': function (d) {
 
32022                     return 'pattern-color-' + d[0];
 
32026         patterns.append('image')
 
32033             .attr('xlink:href', function (d) {
 
32034                 return context.imagePath('pattern/' + d[1] + '.png');
 
32039             .data([12, 18, 20, 32, 45])
 
32040             .enter().append('clipPath')
 
32041             .attr('id', function (d) {
 
32042                 return 'clip-square-' + d;
 
32047             .attr('width', function (d) {
 
32050             .attr('height', function (d) {
 
32054         defs.call(SVGSpriteDefinition(
 
32056             context.imagePath('iD-sprite.svg')));
 
32058         defs.call(SVGSpriteDefinition(
 
32060             context.imagePath('maki-sprite.svg')));
 
32063 iD.svg.Gpx = function(projection, context, dispatch) {
 
32064     var showLabels = true,
 
32068         if (iD.svg.Gpx.initialized) return;  // run once
 
32070         iD.svg.Gpx.geojson = {};
 
32071         iD.svg.Gpx.enabled = true;
 
32074             d3.event.stopPropagation();
 
32075             d3.event.preventDefault();
 
32076             d3.event.dataTransfer.dropEffect = 'copy';
 
32080             .attr('dropzone', 'copy')
 
32081             .on('drop.localgpx', function() {
 
32082                 d3.event.stopPropagation();
 
32083                 d3.event.preventDefault();
 
32084                 if (!iD.detect().filedrop) return;
 
32085                 drawGpx.files(d3.event.dataTransfer.files);
 
32087             .on('dragenter.localgpx', over)
 
32088             .on('dragexit.localgpx', over)
 
32089             .on('dragover.localgpx', over);
 
32091         iD.svg.Gpx.initialized = true;
 
32095     function drawGpx(surface) {
 
32096         var geojson = iD.svg.Gpx.geojson,
 
32097             enabled = iD.svg.Gpx.enabled;
 
32099         layer = surface.selectAll('.layer-gpx')
 
32100             .data(enabled ? [0] : []);
 
32104             .attr('class', 'layer-gpx');
 
32116             .attr('class', 'gpx');
 
32121         var path = d3.geo.path()
 
32122             .projection(projection);
 
32128         var labels = layer.selectAll('text')
 
32129             .data(showLabels && geojson.features ? geojson.features : []);
 
32133             .attr('class', 'gpx');
 
32139             .text(function(d) {
 
32140                 return d.properties.desc || d.properties.name;
 
32142             .attr('x', function(d) {
 
32143                 var centroid = path.centroid(d);
 
32144                 return centroid[0] + 7;
 
32146             .attr('y', function(d) {
 
32147                 var centroid = path.centroid(d);
 
32148                 return centroid[1];
 
32153     function toDom(x) {
 
32154         return (new DOMParser()).parseFromString(x, 'text/xml');
 
32157     drawGpx.showLabels = function(_) {
 
32158         if (!arguments.length) return showLabels;
 
32163     drawGpx.enabled = function(_) {
 
32164         if (!arguments.length) return iD.svg.Gpx.enabled;
 
32165         iD.svg.Gpx.enabled = _;
 
32170     drawGpx.hasGpx = function() {
 
32171         var geojson = iD.svg.Gpx.geojson;
 
32172         return (!(_.isEmpty(geojson) || _.isEmpty(geojson.features)));
 
32175     drawGpx.geojson = function(gj) {
 
32176         if (!arguments.length) return iD.svg.Gpx.geojson;
 
32177         if (_.isEmpty(gj) || _.isEmpty(gj.features)) return this;
 
32178         iD.svg.Gpx.geojson = gj;
 
32183     drawGpx.url = function(url) {
 
32184         d3.text(url, function(err, data) {
 
32186                 drawGpx.geojson(toGeoJSON.gpx(toDom(data)));
 
32192     drawGpx.files = function(fileList) {
 
32193         if (!fileList.length) return this;
 
32194         var f = fileList[0],
 
32195             reader = new FileReader();
 
32197         reader.onload = function(e) {
 
32198             drawGpx.geojson(toGeoJSON.gpx(toDom(e.target.result))).fitZoom();
 
32201         reader.readAsText(f);
 
32205     drawGpx.fitZoom = function() {
 
32206         if (!this.hasGpx()) return this;
 
32207         var geojson = iD.svg.Gpx.geojson;
 
32209         var map = context.map(),
 
32210             viewport = map.trimmedExtent().polygon(),
 
32211             coords = _.reduce(geojson.features, function(coords, feature) {
 
32212                 var c = feature.geometry.coordinates;
 
32213                 return _.union(coords, feature.geometry.type === 'Point' ? [c] : c);
 
32216         if (!iD.geo.polygonIntersectsPolygon(viewport, coords, true)) {
 
32217             var extent = iD.geo.Extent(d3.geo.bounds(geojson));
 
32218             map.centerZoom(extent.center(), map.trimmedExtentZoom(extent));
 
32227 iD.svg.Icon = function(name, svgklass, useklass) {
 
32228     return function drawIcon(selection) {
 
32229         selection.selectAll('svg')
 
32233             .attr('class', 'icon ' + (svgklass || ''))
 
32235             .attr('xlink:href', name)
 
32236             .attr('class', useklass);
 
32239 iD.svg.Labels = function(projection, context) {
 
32240     var path = d3.geo.path().projection(projection);
 
32242     // Replace with dict and iterate over entities tags instead?
 
32243     var label_stack = [
 
32244         ['line', 'aeroway'],
 
32245         ['line', 'highway'],
 
32246         ['line', 'railway'],
 
32247         ['line', 'waterway'],
 
32248         ['area', 'aeroway'],
 
32249         ['area', 'amenity'],
 
32250         ['area', 'building'],
 
32251         ['area', 'historic'],
 
32252         ['area', 'leisure'],
 
32253         ['area', 'man_made'],
 
32254         ['area', 'natural'],
 
32256         ['area', 'tourism'],
 
32257         ['point', 'aeroway'],
 
32258         ['point', 'amenity'],
 
32259         ['point', 'building'],
 
32260         ['point', 'historic'],
 
32261         ['point', 'leisure'],
 
32262         ['point', 'man_made'],
 
32263         ['point', 'natural'],
 
32265         ['point', 'tourism'],
 
32271     var default_size = 12;
 
32273     var font_sizes = label_stack.map(function(d) {
 
32274         var style = iD.util.getStyle('text.' + d[0] + '.tag-' + d[1]),
 
32275             m = style && style.cssText.match('font-size: ([0-9]{1,2})px;');
 
32276         if (m) return parseInt(m[1], 10);
 
32278         style = iD.util.getStyle('text.' + d[0]);
 
32279         m = style && style.cssText.match('font-size: ([0-9]{1,2})px;');
 
32280         if (m) return parseInt(m[1], 10);
 
32282         return default_size;
 
32287     var pointOffsets = [
 
32288         [15, -11, 'start'], // right
 
32289         [10, -11, 'start'], // unused right now
 
32293     var lineOffsets = [50, 45, 55, 40, 60, 35, 65, 30, 70, 25,
 
32294         75, 20, 80, 15, 95, 10, 90, 5, 95];
 
32297     var noIcons = ['building', 'landuse', 'natural'];
 
32298     function blacklisted(preset) {
 
32299         return _.some(noIcons, function(s) {
 
32300             return preset.id.indexOf(s) >= 0;
 
32304     function get(array, prop) {
 
32305         return function(d, i) { return array[i][prop]; };
 
32308     var textWidthCache = {};
 
32310     function textWidth(text, size, elem) {
 
32311         var c = textWidthCache[size];
 
32312         if (!c) c = textWidthCache[size] = {};
 
32318             c[text] = elem.getComputedTextLength();
 
32322             var str = encodeURIComponent(text).match(/%[CDEFcdef]/g);
 
32323             if (str === null) {
 
32324                 return size / 3 * 2 * text.length;
 
32326                 return size / 3 * (2 * text.length + str.length);
 
32331     function drawLineLabels(group, entities, filter, classes, labels) {
 
32332         var texts = group.selectAll('text.' + classes)
 
32334             .data(entities, iD.Entity.key);
 
32338             .attr('class', function(d, i) { return classes + ' ' + labels[i].classes + ' ' + d.id; })
 
32339             .append('textPath')
 
32340             .attr('class', 'textpath');
 
32343         texts.selectAll('.textpath')
 
32345             .data(entities, iD.Entity.key)
 
32347                 'startOffset': '50%',
 
32348                 'xlink:href': function(d) { return '#labelpath-' + d.id; }
 
32350             .text(iD.util.displayName);
 
32352         texts.exit().remove();
 
32355     function drawLinePaths(group, entities, filter, classes, labels) {
 
32356         var halos = group.selectAll('path')
 
32358             .data(entities, iD.Entity.key);
 
32362             .style('stroke-width', get(labels, 'font-size'))
 
32363             .attr('id', function(d) { return 'labelpath-' + d.id; })
 
32364             .attr('class', classes);
 
32366         halos.attr('d', get(labels, 'lineString'));
 
32368         halos.exit().remove();
 
32371     function drawPointLabels(group, entities, filter, classes, labels) {
 
32372         var texts = group.selectAll('text.' + classes)
 
32374             .data(entities, iD.Entity.key);
 
32378             .attr('class', function(d, i) { return classes + ' ' + labels[i].classes + ' ' + d.id; });
 
32380         texts.attr('x', get(labels, 'x'))
 
32381             .attr('y', get(labels, 'y'))
 
32382             .style('text-anchor', get(labels, 'textAnchor'))
 
32383             .text(iD.util.displayName)
 
32384             .each(function(d, i) { textWidth(iD.util.displayName(d), labels[i].height, this); });
 
32386         texts.exit().remove();
 
32390     function drawAreaLabels(group, entities, filter, classes, labels) {
 
32391         entities = entities.filter(hasText);
 
32392         labels = labels.filter(hasText);
 
32393         return drawPointLabels(group, entities, filter, classes, labels);
 
32395         function hasText(d, i) {
 
32396             return labels[i].hasOwnProperty('x') && labels[i].hasOwnProperty('y');
 
32400     function drawAreaIcons(group, entities, filter, classes, labels) {
 
32401         var icons = group.selectAll('use')
 
32403             .data(entities, iD.Entity.key);
 
32407             .attr('class', 'icon areaicon')
 
32408             .attr('width', '18px')
 
32409             .attr('height', '18px');
 
32411         icons.attr('transform', get(labels, 'transform'))
 
32412             .attr('xlink:href', function(d) {
 
32413                 var icon = context.presets().match(d, context.graph()).icon;
 
32414                 return '#' + icon + (icon === 'hairdresser' ? '-24': '-18');    // workaround: maki hairdresser-18 broken?
 
32418         icons.exit().remove();
 
32421     function reverse(p) {
 
32422         var angle = Math.atan2(p[1][1] - p[0][1], p[1][0] - p[0][0]);
 
32423         return !(p[0][0] < p[p.length - 1][0] && angle < Math.PI/2 && angle > -Math.PI/2);
 
32426     function lineString(nodes) {
 
32427         return 'M' + nodes.join('L');
 
32430     function subpath(nodes, from, to) {
 
32431         function segmentLength(i) {
 
32432             var dx = nodes[i][0] - nodes[i + 1][0];
 
32433             var dy = nodes[i][1] - nodes[i + 1][1];
 
32434             return Math.sqrt(dx * dx + dy * dy);
 
32438             start, end, i0, i1;
 
32439         for (var i = 0; i < nodes.length - 1; i++) {
 
32440             var current = segmentLength(i);
 
32442             if (!start && sofar + current >= from) {
 
32443                 portion = (from - sofar) / current;
 
32445                     nodes[i][0] + portion * (nodes[i + 1][0] - nodes[i][0]),
 
32446                     nodes[i][1] + portion * (nodes[i + 1][1] - nodes[i][1])
 
32450             if (!end && sofar + current >= to) {
 
32451                 portion = (to - sofar) / current;
 
32453                     nodes[i][0] + portion * (nodes[i + 1][0] - nodes[i][0]),
 
32454                     nodes[i][1] + portion * (nodes[i + 1][1] - nodes[i][1])
 
32461         var ret = nodes.slice(i0, i1);
 
32462         ret.unshift(start);
 
32468     function hideOnMouseover() {
 
32469         var layers = d3.select(this)
 
32470             .selectAll('.layer-label, .layer-halo');
 
32472         layers.selectAll('.proximate')
 
32473             .classed('proximate', false);
 
32475         var mouse = context.mouse(),
 
32477             rect = [mouse[0] - pad, mouse[1] - pad, mouse[0] + pad, mouse[1] + pad],
 
32478             ids = _.map(rtree.search(rect), 'id');
 
32480         if (!ids.length) return;
 
32481         layers.selectAll('.' + ids.join(', .'))
 
32482             .classed('proximate', true);
 
32485     var rtree = rbush(),
 
32488     function drawLabels(surface, graph, entities, filter, dimensions, fullRedraw) {
 
32489         var hidePoints = !surface.selectAll('.node.point').node();
 
32491         var labelable = [], i, k, entity;
 
32492         for (i = 0; i < label_stack.length; i++) labelable.push([]);
 
32498             for (i = 0; i < entities.length; i++) {
 
32499                 rtree.remove(rectangles[entities[i].id]);
 
32503         // Split entities into groups specified by label_stack
 
32504         for (i = 0; i < entities.length; i++) {
 
32505             entity = entities[i];
 
32506             var geometry = entity.geometry(graph);
 
32508             if (geometry === 'vertex')
 
32510             if (hidePoints && geometry === 'point')
 
32513             var preset = geometry === 'area' && context.presets().match(entity, graph),
 
32514                 icon = preset && !blacklisted(preset) && preset.icon;
 
32516             if (!icon && !iD.util.displayName(entity))
 
32519             for (k = 0; k < label_stack.length; k++) {
 
32520                 if (geometry === label_stack[k][0] && entity.tags[label_stack[k][1]]) {
 
32521                     labelable[k].push(entity);
 
32539         // Try and find a valid label for labellable entities
 
32540         for (k = 0; k < labelable.length; k++) {
 
32541             var font_size = font_sizes[k];
 
32542             for (i = 0; i < labelable[k].length; i++) {
 
32543                 entity = labelable[k][i];
 
32544                 var name = iD.util.displayName(entity),
 
32545                     width = name && textWidth(name, font_size),
 
32547                 if (entity.geometry(graph) === 'point') {
 
32548                     p = getPointLabel(entity, width, font_size);
 
32549                 } else if (entity.geometry(graph) === 'line') {
 
32550                     p = getLineLabel(entity, width, font_size);
 
32551                 } else if (entity.geometry(graph) === 'area') {
 
32552                     p = getAreaLabel(entity, width, font_size);
 
32555                     p.classes = entity.geometry(graph) + ' tag-' + label_stack[k][1];
 
32556                     positions[entity.geometry(graph)].push(p);
 
32557                     labelled[entity.geometry(graph)].push(entity);
 
32562         function getPointLabel(entity, width, height) {
 
32563             var coord = projection(entity.loc),
 
32565                 offset = pointOffsets[0],
 
32569                     x: coord[0] + offset[0],
 
32570                     y: coord[1] + offset[1],
 
32571                     textAnchor: offset[2]
 
32573             var rect = [p.x - m, p.y - m, p.x + width + m, p.y + height + m];
 
32574             if (tryInsert(rect, entity.id)) return p;
 
32578         function getLineLabel(entity, width, height) {
 
32579             var nodes = _.map(graph.childNodes(entity), 'loc').map(projection),
 
32580                 length = iD.geo.pathLength(nodes);
 
32581             if (length < width + 20) return;
 
32583             for (var i = 0; i < lineOffsets.length; i++) {
 
32584                 var offset = lineOffsets[i],
 
32585                     middle = offset / 100 * length,
 
32586                     start = middle - width/2;
 
32587                 if (start < 0 || start + width > length) continue;
 
32588                 var sub = subpath(nodes, start, start + width),
 
32589                     rev = reverse(sub),
 
32591                         Math.min(sub[0][0], sub[sub.length - 1][0]) - 10,
 
32592                         Math.min(sub[0][1], sub[sub.length - 1][1]) - 10,
 
32593                         Math.max(sub[0][0], sub[sub.length - 1][0]) + 20,
 
32594                         Math.max(sub[0][1], sub[sub.length - 1][1]) + 30
 
32596                 if (rev) sub = sub.reverse();
 
32597                 if (tryInsert(rect, entity.id)) return {
 
32598                     'font-size': height + 2,
 
32599                     lineString: lineString(sub),
 
32600                     startOffset: offset + '%'
 
32605         function getAreaLabel(entity, width, height) {
 
32606             var centroid = path.centroid(entity.asGeoJSON(graph, true)),
 
32607                 extent = entity.extent(graph),
 
32608                 entitywidth = projection(extent[1])[0] - projection(extent[0])[0],
 
32611             if (isNaN(centroid[0]) || entitywidth < 20) return;
 
32613             var iconX = centroid[0] - (iconSize/2),
 
32614                 iconY = centroid[1] - (iconSize/2),
 
32615                 textOffset = iconSize + 5;
 
32618                 transform: 'translate(' + iconX + ',' + iconY + ')'
 
32621             if (width && entitywidth >= width + 20) {
 
32623                 p.y = centroid[1] + textOffset;
 
32624                 p.textAnchor = 'middle';
 
32626                 rect = [p.x - width/2, p.y, p.x + width/2, p.y + height + textOffset];
 
32628                 rect = [iconX, iconY, iconX + iconSize, iconY + iconSize];
 
32631             if (tryInsert(rect, entity.id)) return p;
 
32635         function tryInsert(rect, id) {
 
32636             // Check that label is visible
 
32637             if (rect[0] < 0 || rect[1] < 0 || rect[2] > dimensions[0] ||
 
32638                 rect[3] > dimensions[1]) return false;
 
32639             var v = rtree.search(rect).length === 0;
 
32642                 rtree.insert(rect);
 
32643                 rectangles[id] = rect;
 
32648         var label = surface.selectAll('.layer-label'),
 
32649             halo = surface.selectAll('.layer-halo');
 
32652         drawPointLabels(label, labelled.point, filter, 'pointlabel', positions.point);
 
32653         drawPointLabels(halo, labelled.point, filter, 'pointlabel-halo', positions.point);
 
32656         drawLinePaths(halo, labelled.line, filter, '', positions.line);
 
32657         drawLineLabels(label, labelled.line, filter, 'linelabel', positions.line);
 
32658         drawLineLabels(halo, labelled.line, filter, 'linelabel-halo', positions.line);
 
32661         drawAreaLabels(label, labelled.area, filter, 'arealabel', positions.area);
 
32662         drawAreaLabels(halo, labelled.area, filter, 'arealabel-halo', positions.area);
 
32663         drawAreaIcons(label, labelled.area, filter, 'arealabel-icon', positions.area);
 
32666         var showDebug = context.getDebug('collision');
 
32667         var debug = label.selectAll('.layer-label-debug')
 
32668             .data(showDebug ? [true] : []);
 
32672             .attr('class', 'layer-label-debug');
 
32678             var gj = rtree.all().map(function(d) {
 
32679                 return { type: 'Polygon', coordinates: [[
 
32688             var debugboxes = debug.selectAll('.debug').data(gj);
 
32692                 .attr('class', 'debug yellow');
 
32698                 .attr('d', d3.geo.path().projection(null));
 
32702     drawLabels.supersurface = function(supersurface) {
 
32704             .on('mousemove.hidelabels', hideOnMouseover)
 
32705             .on('mousedown.hidelabels', function () {
 
32706                 supersurface.on('mousemove.hidelabels', null);
 
32708             .on('mouseup.hidelabels', function () {
 
32709                 supersurface.on('mousemove.hidelabels', hideOnMouseover);
 
32715 iD.svg.Layers = function(projection, context) {
 
32716     var dispatch = d3.dispatch('change'),
 
32717         svg = d3.select(null),
 
32719             { id: 'osm', layer: iD.svg.Osm(projection, context, dispatch) },
 
32720             { id: 'gpx', layer: iD.svg.Gpx(projection, context, dispatch) },
 
32721             { id: 'mapillary-images', layer: iD.svg.MapillaryImages(projection, context, dispatch) },
 
32722             { id: 'mapillary-signs',  layer: iD.svg.MapillarySigns(projection, context, dispatch) },
 
32723             { id: 'debug', layer: iD.svg.Debug(projection, context, dispatch) }
 
32727     function drawLayers(selection) {
 
32728         svg = selection.selectAll('.surface')
 
32733             .attr('class', 'surface')
 
32736         var groups = svg.selectAll('.data-layer')
 
32741             .attr('class', function(d) { return 'data-layer data-layer-' + d.id; });
 
32744             .each(function(d) { d3.select(this).call(d.layer); });
 
32750     drawLayers.all = function() {
 
32754     drawLayers.layer = function(id) {
 
32755         var obj = _.find(layers, function(o) {return o.id === id;});
 
32756         return obj && obj.layer;
 
32759     drawLayers.only = function(what) {
 
32760         var arr = [].concat(what);
 
32761         drawLayers.remove(_.difference(_.map(layers, 'id'), arr));
 
32765     drawLayers.remove = function(what) {
 
32766         var arr = [].concat(what);
 
32767         arr.forEach(function(id) {
 
32768             layers = _.reject(layers, function(o) {return o.id === id;});
 
32774     drawLayers.add = function(what) {
 
32775         var arr = [].concat(what);
 
32776         arr.forEach(function(obj) {
 
32777             if ('id' in obj && 'layer' in obj) {
 
32785     drawLayers.dimensions = function(_) {
 
32786         if (!arguments.length) return svg.dimensions();
 
32788         layers.forEach(function(obj) {
 
32789             if (obj.layer.dimensions) {
 
32790                 obj.layer.dimensions(_);
 
32797     return d3.rebind(drawLayers, dispatch, 'on');
 
32799 iD.svg.Lines = function(projection) {
 
32801     var highway_stack = {
 
32816     function waystack(a, b) {
 
32817         var as = 0, bs = 0;
 
32819         if (a.tags.highway) { as -= highway_stack[a.tags.highway]; }
 
32820         if (b.tags.highway) { bs -= highway_stack[b.tags.highway]; }
 
32824     return function drawLines(surface, graph, entities, filter) {
 
32825         var ways = [], pathdata = {}, onewaydata = {},
 
32826             getPath = iD.svg.Path(projection, graph);
 
32828         for (var i = 0; i < entities.length; i++) {
 
32829             var entity = entities[i],
 
32830                 outer = iD.geo.simpleMultipolygonOuterMember(entity, graph);
 
32832                 ways.push(entity.mergeTags(outer.tags));
 
32833             } else if (entity.geometry(graph) === 'line') {
 
32838         ways = ways.filter(getPath);
 
32840         pathdata = _.groupBy(ways, function(way) { return way.layer(); });
 
32842         _.forOwn(pathdata, function(v, k) {
 
32843             onewaydata[k] = _(v)
 
32844                 .filter(function(d) { return d.isOneWay(); })
 
32845                 .map(iD.svg.OneWaySegments(projection, graph, 35))
 
32850         var layergroup = surface
 
32851             .selectAll('.layer-lines')
 
32852             .selectAll('g.layergroup')
 
32853             .data(d3.range(-10, 11));
 
32857             .attr('class', function(d) { return 'layer layergroup layer' + String(d); });
 
32860         var linegroup = layergroup
 
32861             .selectAll('g.linegroup')
 
32862             .data(['shadow', 'casing', 'stroke']);
 
32866             .attr('class', function(d) { return 'layer linegroup line-' + d; });
 
32869         var lines = linegroup
 
32873                 function() { return pathdata[this.parentNode.parentNode.__data__] || []; },
 
32877         // Optimization: call simple TagClasses only on enter selection. This
 
32878         // works because iD.Entity.key is defined to include the entity v attribute.
 
32881             .attr('class', function(d) { return 'way line ' + this.parentNode.__data__ + ' ' + d.id; })
 
32882             .call(iD.svg.TagClasses());
 
32886             .attr('d', getPath)
 
32887             .call(iD.svg.TagClasses().tags(iD.svg.RelationMemberTags(graph)));
 
32893         var onewaygroup = layergroup
 
32894             .selectAll('g.onewaygroup')
 
32897         onewaygroup.enter()
 
32899             .attr('class', 'layer onewaygroup');
 
32902         var oneways = onewaygroup
 
32906                 function() { return onewaydata[this.parentNode.parentNode.__data__] || []; },
 
32907                 function(d) { return [d.id, d.index]; }
 
32912             .attr('class', 'oneway')
 
32913             .attr('marker-mid', 'url(#oneway-marker)');
 
32916             .attr('d', function(d) { return d.d; });
 
32918         if (iD.detect().ie) {
 
32919             oneways.each(function() { this.parentNode.insertBefore(this, this); });
 
32927 iD.svg.MapillaryImages = function(projection, context, dispatch) {
 
32928     var debouncedRedraw = _.debounce(function () { dispatch.change(); }, 1000),
 
32930         layer = d3.select(null),
 
32935         if (iD.svg.MapillaryImages.initialized) return;  // run once
 
32936         iD.svg.MapillaryImages.enabled = false;
 
32937         iD.svg.MapillaryImages.initialized = true;
 
32940     function getMapillary() {
 
32941         if (iD.services.mapillary && !_mapillary) {
 
32942             _mapillary = iD.services.mapillary();
 
32943             _mapillary.on('loadedImages', debouncedRedraw);
 
32944         } else if (!iD.services.mapillary && _mapillary) {
 
32951     function showLayer() {
 
32952         var mapillary = getMapillary();
 
32953         if (!mapillary) return;
 
32955         mapillary.loadViewer();
 
32959             .style('opacity', 0)
 
32962             .style('opacity', 1)
 
32963             .each('end', debouncedRedraw);
 
32966     function hideLayer() {
 
32967         var mapillary = getMapillary();
 
32969             mapillary.hideViewer();
 
32972         debouncedRedraw.cancel();
 
32977             .style('opacity', 0)
 
32978             .each('end', editOff);
 
32981     function editOn() {
 
32982         layer.style('display', 'block');
 
32985     function editOff() {
 
32986         layer.selectAll('.viewfield-group').remove();
 
32987         layer.style('display', 'none');
 
32990     function click(d) {
 
32991         var mapillary = getMapillary();
 
32992         if (!mapillary) return;
 
32994         context.map().centerEase(d.loc);
 
32997             .setSelectedImage(d.key, true)
 
32998             .updateViewer(d.key, context)
 
33002     function transform(d) {
 
33003         var t = iD.svg.PointTransform(projection)(d);
 
33004         if (d.ca) t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
 
33008     function update() {
 
33009         var mapillary = getMapillary(),
 
33010             data = (mapillary ? mapillary.images(projection, layer.dimensions()) : []),
 
33011             imageKey = mapillary ? mapillary.getSelectedImage() : null;
 
33013         var markers = layer.selectAll('.viewfield-group')
 
33014             .data(data, function(d) { return d.key; });
 
33017         var enter = markers.enter()
 
33019             .attr('class', 'viewfield-group')
 
33020             .classed('selected', function(d) { return d.key === imageKey; })
 
33021             .on('click', click);
 
33023         enter.append('path')
 
33024             .attr('class', 'viewfield')
 
33025             .attr('transform', 'scale(1.5,1.5),translate(-8, -13)')
 
33026             .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');
 
33028         enter.append('circle')
 
33039             .attr('transform', transform);
 
33042     function drawImages(selection) {
 
33043         var enabled = iD.svg.MapillaryImages.enabled,
 
33044             mapillary = getMapillary();
 
33046         layer = selection.selectAll('.layer-mapillary-images')
 
33047             .data(mapillary ? [0] : []);
 
33051             .attr('class', 'layer-mapillary-images')
 
33052             .style('display', enabled ? 'block' : 'none');
 
33058             if (mapillary && ~~context.map().zoom() >= minZoom) {
 
33061                 mapillary.loadImages(projection, layer.dimensions());
 
33068     drawImages.enabled = function(_) {
 
33069         if (!arguments.length) return iD.svg.MapillaryImages.enabled;
 
33070         iD.svg.MapillaryImages.enabled = _;
 
33071         if (iD.svg.MapillaryImages.enabled) {
 
33080     drawImages.supported = function() {
 
33081         return !!getMapillary();
 
33084     drawImages.dimensions = function(_) {
 
33085         if (!arguments.length) return layer.dimensions();
 
33086         layer.dimensions(_);
 
33093 iD.svg.MapillarySigns = function(projection, context, dispatch) {
 
33094     var debouncedRedraw = _.debounce(function () { dispatch.change(); }, 1000),
 
33096         layer = d3.select(null),
 
33101         if (iD.svg.MapillarySigns.initialized) return;  // run once
 
33102         iD.svg.MapillarySigns.enabled = false;
 
33103         iD.svg.MapillarySigns.initialized = true;
 
33106     function getMapillary() {
 
33107         if (iD.services.mapillary && !_mapillary) {
 
33108             _mapillary = iD.services.mapillary().on('loadedSigns', debouncedRedraw);
 
33109         } else if (!iD.services.mapillary && _mapillary) {
 
33115     function showLayer() {
 
33120     function hideLayer() {
 
33121         debouncedRedraw.cancel();
 
33125     function editOn() {
 
33126         layer.style('display', 'block');
 
33129     function editOff() {
 
33130         layer.selectAll('.icon-sign').remove();
 
33131         layer.style('display', 'none');
 
33134     function click(d) {
 
33135         var mapillary = getMapillary();
 
33136         if (!mapillary) return;
 
33138         context.map().centerEase(d.loc);
 
33141             .setSelectedImage(d.key, true)
 
33142             .updateViewer(d.key, context)
 
33146     function update() {
 
33147         var mapillary = getMapillary(),
 
33148             data = (mapillary ? mapillary.signs(projection, layer.dimensions()) : []),
 
33149             imageKey = mapillary ? mapillary.getSelectedImage() : null;
 
33151         var signs = layer.selectAll('.icon-sign')
 
33152             .data(data, function(d) { return d.key; });
 
33155         var enter = signs.enter()
 
33156             .append('foreignObject')
 
33157             .attr('class', 'icon-sign')
 
33158             .attr('width', '32px')      // for Firefox
 
33159             .attr('height', '32px')     // for Firefox
 
33160             .classed('selected', function(d) { return d.key === imageKey; })
 
33161             .on('click', click);
 
33164             .append('xhtml:body')
 
33165             .html(mapillary.signHTML);
 
33173             .attr('transform', iD.svg.PointTransform(projection));
 
33176     function drawSigns(selection) {
 
33177         var enabled = iD.svg.MapillarySigns.enabled,
 
33178             mapillary = getMapillary();
 
33180         layer = selection.selectAll('.layer-mapillary-signs')
 
33181             .data(mapillary ? [0] : []);
 
33185             .attr('class', 'layer-mapillary-signs')
 
33186             .style('display', enabled ? 'block' : 'none')
 
33187             .attr('transform', 'translate(-16, -16)');  // center signs on loc
 
33193             if (mapillary && ~~context.map().zoom() >= minZoom) {
 
33196                 mapillary.loadSigns(context, projection, layer.dimensions());
 
33203     drawSigns.enabled = function(_) {
 
33204         if (!arguments.length) return iD.svg.MapillarySigns.enabled;
 
33205         iD.svg.MapillarySigns.enabled = _;
 
33206         if (iD.svg.MapillarySigns.enabled) {
 
33215     drawSigns.supported = function() {
 
33216         var mapillary = getMapillary();
 
33217         return (mapillary && mapillary.signsSupported());
 
33220     drawSigns.dimensions = function(_) {
 
33221         if (!arguments.length) return layer.dimensions();
 
33222         layer.dimensions(_);
 
33229 iD.svg.Midpoints = function(projection, context) {
 
33230     return function drawMidpoints(surface, graph, entities, filter, extent) {
 
33231         var poly = extent.polygon(),
 
33234         for (var i = 0; i < entities.length; i++) {
 
33235             var entity = entities[i];
 
33237             if (entity.type !== 'way')
 
33239             if (!filter(entity))
 
33241             if (context.selectedIDs().indexOf(entity.id) < 0)
 
33244             var nodes = graph.childNodes(entity);
 
33245             for (var j = 0; j < nodes.length - 1; j++) {
 
33249                     id = [a.id, b.id].sort().join('-');
 
33251                 if (midpoints[id]) {
 
33252                     midpoints[id].parents.push(entity);
 
33254                     if (iD.geo.euclideanDistance(projection(a.loc), projection(b.loc)) > 40) {
 
33255                         var point = iD.geo.interp(a.loc, b.loc, 0.5),
 
33258                         if (extent.intersects(point)) {
 
33261                             for (var k = 0; k < 4; k++) {
 
33262                                 point = iD.geo.lineIntersection([a.loc, b.loc], [poly[k], poly[k+1]]);
 
33264                                     iD.geo.euclideanDistance(projection(a.loc), projection(point)) > 20 &&
 
33265                                     iD.geo.euclideanDistance(projection(b.loc), projection(point)) > 20)
 
33278                                 edge: [a.id, b.id],
 
33287         function midpointFilter(d) {
 
33288             if (midpoints[d.id])
 
33291             for (var i = 0; i < d.parents.length; i++)
 
33292                 if (filter(d.parents[i]))
 
33298         var groups = surface.selectAll('.layer-hit').selectAll('g.midpoint')
 
33299             .filter(midpointFilter)
 
33300             .data(_.values(midpoints), function(d) { return d.id; });
 
33302         var enter = groups.enter()
 
33303             .insert('g', ':first-child')
 
33304             .attr('class', 'midpoint');
 
33306         enter.append('polygon')
 
33307             .attr('points', '-6,8 10,0 -6,-8')
 
33308             .attr('class', 'shadow');
 
33310         enter.append('polygon')
 
33311             .attr('points', '-3,4 5,0 -3,-4')
 
33312             .attr('class', 'fill');
 
33315             .attr('transform', function(d) {
 
33316                 var translate = iD.svg.PointTransform(projection),
 
33317                     a = context.entity(d.edge[0]),
 
33318                     b = context.entity(d.edge[1]),
 
33319                     angle = Math.round(iD.geo.angle(a, b, projection) * (180 / Math.PI));
 
33320                 return translate(d) + ' rotate(' + angle + ')';
 
33322             .call(iD.svg.TagClasses().tags(
 
33323                 function(d) { return d.parents[0].tags; }
 
33326         // Propagate data bindings.
 
33327         groups.select('polygon.shadow');
 
33328         groups.select('polygon.fill');
 
33334 iD.svg.Osm = function() {
 
33335     return function drawOsm(selection) {
 
33336         var layers = selection.selectAll('.layer-osm')
 
33337             .data(['areas', 'lines', 'hit', 'halo', 'label']);
 
33339         layers.enter().append('g')
 
33340             .attr('class', function(d) { return 'layer-osm layer-' + d; });
 
33343 iD.svg.Points = function(projection, context) {
 
33344     function markerPath(selection, klass) {
 
33346             .attr('class', klass)
 
33347             .attr('transform', 'translate(-8, -23)')
 
33348             .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');
 
33351     function sortY(a, b) {
 
33352         return b.loc[1] - a.loc[1];
 
33355     return function drawPoints(surface, graph, entities, filter) {
 
33356         var wireframe = surface.classed('fill-wireframe'),
 
33357             points = wireframe ? [] : _.filter(entities, function(e) {
 
33358                 return e.geometry(graph) === 'point';
 
33361         points.sort(sortY);
 
33363         var groups = surface.selectAll('.layer-hit').selectAll('g.point')
 
33365             .data(points, iD.Entity.key);
 
33367         var group = groups.enter()
 
33369             .attr('class', function(d) { return 'node point ' + d.id; })
 
33372         group.append('path')
 
33373             .call(markerPath, 'shadow');
 
33375         group.append('path')
 
33376             .call(markerPath, 'stroke');
 
33378         group.append('use')
 
33379             .attr('transform', 'translate(-6, -20)')
 
33380             .attr('class', 'icon')
 
33381             .attr('width', '12px')
 
33382             .attr('height', '12px');
 
33384         groups.attr('transform', iD.svg.PointTransform(projection))
 
33385             .call(iD.svg.TagClasses());
 
33387         // Selecting the following implicitly
 
33388         // sets the data (point entity) on the element
 
33389         groups.select('.shadow');
 
33390         groups.select('.stroke');
 
33391         groups.select('.icon')
 
33392             .attr('xlink:href', function(entity) {
 
33393                 var preset = context.presets().match(entity, graph);
 
33394                 return preset.icon ? '#' + preset.icon + '-12' : '';
 
33401 iD.svg.TagClasses = function() {
 
33403             'building', 'highway', 'railway', 'waterway', 'aeroway',
 
33404             'motorway', 'boundary', 'power', 'amenity', 'natural', 'landuse',
 
33408             'proposed', 'construction', 'disused', 'abandoned', 'dismantled',
 
33409             'razed', 'demolished', 'obliterated'
 
33412             'oneway', 'bridge', 'tunnel', 'embankment', 'cutting', 'barrier',
 
33413             'surface', 'tracktype', 'crossing'
 
33415         tagClassRe = /^tag-/,
 
33416         tags = function(entity) { return entity.tags; };
 
33419     var tagClasses = function(selection) {
 
33420         selection.each(function tagClassesEach(entity) {
 
33421             var value = this.className,
 
33422                 classes, primary, status;
 
33424             if (value.baseVal !== undefined) value = value.baseVal;
 
33426             classes = value.trim().split(/\s+/).filter(function(name) {
 
33427                 return name.length && !tagClassRe.test(name);
 
33430             var t = tags(entity), i, k, v;
 
33432             // pick at most one primary classification tag..
 
33433             for (i = 0; i < primaries.length; i++) {
 
33436                 if (!v || v === 'no') continue;
 
33439                 if (statuses.indexOf(v) !== -1) {   // e.g. `railway=abandoned`
 
33441                     classes += ' tag-' + k;
 
33443                     classes += ' tag-' + k + ' tag-' + k + '-' + v;
 
33449             // add at most one status tag, only if relates to primary tag..
 
33451                 for (i = 0; i < statuses.length; i++) {
 
33454                     if (!v || v === 'no') continue;
 
33456                     if (v === 'yes') {   // e.g. `railway=rail + abandoned=yes`
 
33459                     else if (primary && primary === v) {  // e.g. `railway=rail + abandoned=railway`
 
33461                     } else if (!primary && primaries.indexOf(v) !== -1) {  // e.g. `abandoned=railway`
 
33464                         classes += ' tag-' + v;
 
33465                     }  // else ignore e.g.  `highway=path + abandoned=railway`
 
33472                 classes += ' tag-status tag-status-' + status;
 
33475             // add any secondary (structure) tags
 
33476             for (i = 0; i < secondaries.length; i++) {
 
33477                 k = secondaries[i];
 
33479                 if (!v || v === 'no') continue;
 
33480                 classes += ' tag-' + k + ' tag-' + k + '-' + v;
 
33483             // For highways, look for surface tagging..
 
33484             if (primary === 'highway') {
 
33485                 var paved = (t.highway !== 'track');
 
33488                     if (k in iD.pavedTags) {
 
33489                         paved = !!iD.pavedTags[k][v];
 
33494                     classes += ' tag-unpaved';
 
33498             classes = classes.trim();
 
33500             if (classes !== value) {
 
33501                 d3.select(this).attr('class', classes);
 
33506     tagClasses.tags = function(_) {
 
33507         if (!arguments.length) return tags;
 
33514 iD.svg.Turns = function(projection) {
 
33515     return function drawTurns(surface, graph, turns) {
 
33516         function key(turn) {
 
33517             return [turn.from.node + turn.via.node + turn.to.node].join('-');
 
33520         function icon(turn) {
 
33521             var u = turn.u ? '-u' : '';
 
33522             if (!turn.restriction)
 
33523                 return '#turn-yes' + u;
 
33524             var restriction = graph.entity(turn.restriction).tags.restriction;
 
33526                 (!turn.indirect_restriction && /^only_/.test(restriction) ? 'only' : 'no') + u;
 
33529         var groups = surface.selectAll('.layer-hit').selectAll('g.turn')
 
33533         var enter = groups.enter().append('g')
 
33534             .attr('class', 'turn');
 
33536         var nEnter = enter.filter(function (turn) { return !turn.u; });
 
33538         nEnter.append('rect')
 
33539             .attr('transform', 'translate(-22, -12)')
 
33540             .attr('width', '44')
 
33541             .attr('height', '24');
 
33543         nEnter.append('use')
 
33544             .attr('transform', 'translate(-22, -12)')
 
33545             .attr('width', '44')
 
33546             .attr('height', '24');
 
33549         var uEnter = enter.filter(function (turn) { return turn.u; });
 
33551         uEnter.append('circle')
 
33554         uEnter.append('use')
 
33555             .attr('transform', 'translate(-16, -16)')
 
33556             .attr('width', '32')
 
33557             .attr('height', '32');
 
33562             .attr('transform', function (turn) {
 
33563                 var v = graph.entity(turn.via.node),
 
33564                     t = graph.entity(turn.to.node),
 
33565                     a = iD.geo.angle(v, t, projection),
 
33566                     p = projection(v.loc),
 
33567                     r = turn.u ? 0 : 60;
 
33569                 return 'translate(' + (r * Math.cos(a) + p[0]) + ',' + (r * Math.sin(a) + p[1]) + ') ' +
 
33570                     'rotate(' + a * 180 / Math.PI + ')';
 
33573         groups.select('use')
 
33574             .attr('xlink:href', icon);
 
33576         groups.select('rect');
 
33577         groups.select('circle');
 
33587 iD.svg.Vertices = function(projection, context) {
 
33589         //       z16-, z17, z18+, tagged
 
33590         shadow: [6,    7.5,   7.5,  11.5],
 
33591         stroke: [2.5,  3.5,   3.5,  7],
 
33592         fill:   [1,    1.5,   1.5,  1.5]
 
33597     function siblingAndChildVertices(ids, graph, extent) {
 
33600         function addChildVertices(entity) {
 
33601             if (!context.features().isHiddenFeature(entity, graph, entity.geometry(graph))) {
 
33603                 if (entity.type === 'way') {
 
33604                     for (i = 0; i < entity.nodes.length; i++) {
 
33605                         addChildVertices(graph.entity(entity.nodes[i]));
 
33607                 } else if (entity.type === 'relation') {
 
33608                     for (i = 0; i < entity.members.length; i++) {
 
33609                         var member = context.hasEntity(entity.members[i].id);
 
33611                             addChildVertices(member);
 
33614                 } else if (entity.intersects(extent, graph)) {
 
33615                     vertices[entity.id] = entity;
 
33620         ids.forEach(function(id) {
 
33621             var entity = context.hasEntity(id);
 
33622             if (entity && entity.type === 'node') {
 
33623                 vertices[entity.id] = entity;
 
33624                 context.graph().parentWays(entity).forEach(function(entity) {
 
33625                     addChildVertices(entity);
 
33627             } else if (entity) {
 
33628                 addChildVertices(entity);
 
33635     function draw(selection, vertices, klass, graph, zoom) {
 
33637             z = (zoom < 17 ? 0 : zoom < 18 ? 1 : 2);
 
33639         var groups = selection
 
33640             .data(vertices, iD.Entity.key);
 
33642         function icon(entity) {
 
33643             if (entity.id in icons) return icons[entity.id];
 
33645                 entity.hasInterestingTags() &&
 
33646                 context.presets().match(entity, graph).icon;
 
33647             return icons[entity.id];
 
33650         function setClass(klass) {
 
33651             return function(entity) {
 
33652                 this.setAttribute('class', 'node vertex ' + klass + ' ' + entity.id);
 
33656         function setAttributes(selection) {
 
33657             ['shadow','stroke','fill'].forEach(function(klass) {
 
33658                 var rads = radiuses[klass];
 
33659                 selection.selectAll('.' + klass)
 
33660                     .each(function(entity) {
 
33661                         var i = z && icon(entity),
 
33663                             r = rads[i ? 3 : z];
 
33664                         this.setAttribute('cx', c);
 
33665                         this.setAttribute('cy', -c);
 
33666                         this.setAttribute('r', r);
 
33667                         if (i && klass === 'fill') {
 
33668                             this.setAttribute('visibility', 'hidden');
 
33670                             this.removeAttribute('visibility');
 
33675             selection.selectAll('use')
 
33678                         this.removeAttribute('visibility');
 
33680                         this.setAttribute('visibility', 'hidden');
 
33685         var enter = groups.enter()
 
33687             .attr('class', function(d) { return 'node vertex ' + klass + ' ' + d.id; });
 
33689         enter.append('circle')
 
33690             .each(setClass('shadow'));
 
33692         enter.append('circle')
 
33693             .each(setClass('stroke'));
 
33695         // Vertices with icons get a `use`.
 
33696         enter.filter(function(d) { return icon(d); })
 
33698             .attr('transform', 'translate(-6, -6)')
 
33699             .attr('xlink:href', function(d) { return '#' + icon(d) + '-12'; })
 
33700             .attr('width', '12px')
 
33701             .attr('height', '12px')
 
33702             .each(setClass('icon'));
 
33704         // Vertices with tags get a fill.
 
33705         enter.filter(function(d) { return d.hasInterestingTags(); })
 
33707             .each(setClass('fill'));
 
33710             .attr('transform', iD.svg.PointTransform(projection))
 
33711             .classed('shared', function(entity) { return graph.isShared(entity); })
 
33712             .call(setAttributes);
 
33718     function drawVertices(surface, graph, entities, filter, extent, zoom) {
 
33719         var selected = siblingAndChildVertices(context.selectedIDs(), graph, extent),
 
33720             wireframe = surface.classed('fill-wireframe'),
 
33723         for (var i = 0; i < entities.length; i++) {
 
33724             var entity = entities[i],
 
33725                 geometry = entity.geometry(graph);
 
33727             if (wireframe && geometry === 'point') {
 
33728                 vertices.push(entity);
 
33732             if (geometry !== 'vertex')
 
33735             if (entity.id in selected ||
 
33736                 entity.hasInterestingTags() ||
 
33737                 entity.isIntersection(graph)) {
 
33738                 vertices.push(entity);
 
33742         surface.selectAll('.layer-hit').selectAll('g.vertex.vertex-persistent')
 
33744             .call(draw, vertices, 'vertex-persistent', graph, zoom);
 
33746         drawHover(surface, graph, extent, zoom);
 
33749     function drawHover(surface, graph, extent, zoom) {
 
33750         var hovered = hover ? siblingAndChildVertices([hover.id], graph, extent) : {};
 
33752         surface.selectAll('.layer-hit').selectAll('g.vertex.vertex-hover')
 
33753             .call(draw, d3.values(hovered), 'vertex-hover', graph, zoom);
 
33756     drawVertices.drawHover = function(surface, graph, target, extent, zoom) {
 
33757         if (target === hover) return;
 
33759         drawHover(surface, graph, extent, zoom);
 
33762     return drawVertices;
 
33764 iD.ui = function(context) {
 
33765     function render(container) {
 
33766         var map = context.map();
 
33768         if (iD.detect().opera) container.classed('opera', true);
 
33770         var hash = iD.behavior.Hash(context);
 
33774         if (!hash.hadHash) {
 
33775             map.centerZoom([0, 0], 2);
 
33778         container.append('svg')
 
33779             .attr('id', 'defs')
 
33780             .call(iD.svg.Defs(context));
 
33782         container.append('div')
 
33783             .attr('id', 'sidebar')
 
33784             .attr('class', 'col4')
 
33787         var content = container.append('div')
 
33788             .attr('id', 'content');
 
33790         var bar = content.append('div')
 
33792             .attr('class', 'fillD');
 
33794         content.append('div')
 
33799             .call(iD.ui.MapInMap(context));
 
33801         content.append('div')
 
33802             .call(iD.ui.Info(context));
 
33805             .attr('class', 'spacer col4');
 
33807         var limiter = bar.append('div')
 
33808             .attr('class', 'limiter');
 
33810         limiter.append('div')
 
33811             .attr('class', 'button-wrap joined col3')
 
33812             .call(iD.ui.Modes(context), limiter);
 
33814         limiter.append('div')
 
33815             .attr('class', 'button-wrap joined col1')
 
33816             .call(iD.ui.UndoRedo(context));
 
33818         limiter.append('div')
 
33819             .attr('class', 'button-wrap col1')
 
33820             .call(iD.ui.Save(context));
 
33823             .attr('class', 'full-screen')
 
33824             .call(iD.ui.FullScreen(context));
 
33827             .attr('class', 'spinner')
 
33828             .call(iD.ui.Spinner(context));
 
33830         var controls = bar.append('div')
 
33831             .attr('class', 'map-controls');
 
33833         controls.append('div')
 
33834             .attr('class', 'map-control zoombuttons')
 
33835             .call(iD.ui.Zoom(context));
 
33837         controls.append('div')
 
33838             .attr('class', 'map-control geolocate-control')
 
33839             .call(iD.ui.Geolocate(context));
 
33841         controls.append('div')
 
33842             .attr('class', 'map-control background-control')
 
33843             .call(iD.ui.Background(context));
 
33845         controls.append('div')
 
33846             .attr('class', 'map-control map-data-control')
 
33847             .call(iD.ui.MapData(context));
 
33849         controls.append('div')
 
33850             .attr('class', 'map-control help-control')
 
33851             .call(iD.ui.Help(context));
 
33853         var about = content.append('div')
 
33854             .attr('id', 'about');
 
33856         about.append('div')
 
33857             .attr('id', 'attrib')
 
33858             .call(iD.ui.Attribution(context));
 
33860         var footer = about.append('div')
 
33861             .attr('id', 'footer')
 
33862             .attr('class', 'fillD');
 
33864         footer.append('div')
 
33865             .attr('class', 'api-status')
 
33866             .call(iD.ui.Status(context));
 
33868         footer.append('div')
 
33869             .attr('id', 'scale-block')
 
33870             .call(iD.ui.Scale(context));
 
33872         var aboutList = footer.append('div')
 
33873             .attr('id', 'info-block')
 
33875             .attr('id', 'about-list');
 
33877         if (!context.embed()) {
 
33878             aboutList.call(iD.ui.Account(context));
 
33881         aboutList.append('li')
 
33883             .attr('target', '_blank')
 
33884             .attr('tabindex', -1)
 
33885             .attr('href', 'https://github.com/openstreetmap/iD')
 
33888         var issueLinks = aboutList.append('li');
 
33890         issueLinks.append('a')
 
33891             .attr('target', '_blank')
 
33892             .attr('tabindex', -1)
 
33893             .attr('href', 'https://github.com/openstreetmap/iD/issues')
 
33894             .call(iD.svg.Icon('#icon-bug', 'light'))
 
33895             .call(bootstrap.tooltip()
 
33896                 .title(t('report_a_bug'))
 
33900         issueLinks.append('a')
 
33901             .attr('target', '_blank')
 
33902             .attr('tabindex', -1)
 
33903             .attr('href', 'https://github.com/openstreetmap/iD/blob/master/CONTRIBUTING.md#translating')
 
33904             .call(iD.svg.Icon('#icon-translate', 'light'))
 
33905             .call(bootstrap.tooltip()
 
33906                 .title(t('help_translate'))
 
33910         aboutList.append('li')
 
33911             .attr('class', 'feature-warning')
 
33912             .attr('tabindex', -1)
 
33913             .call(iD.ui.FeatureInfo(context));
 
33915         aboutList.append('li')
 
33916             .attr('class', 'user-list')
 
33917             .attr('tabindex', -1)
 
33918             .call(iD.ui.Contributors(context));
 
33920         window.onbeforeunload = function() {
 
33921             return context.save();
 
33924         window.onunload = function() {
 
33925             context.history().unlock();
 
33928         var mapDimensions = map.dimensions();
 
33930         d3.select(window).on('resize.editor', function() {
 
33931             mapDimensions = content.dimensions(null);
 
33932             map.dimensions(mapDimensions);
 
33936             return function() {
 
33937                 d3.event.preventDefault();
 
33938                 if (!context.inIntro()) context.pan(d);
 
33945         var keybinding = d3.keybinding('main')
 
33946             .on('⌫', function() { d3.event.preventDefault(); })
 
33947             .on('←', pan([pa, 0]))
 
33948             .on('↑', pan([0, pa]))
 
33949             .on('→', pan([-pa, 0]))
 
33950             .on('↓', pan([0, -pa]))
 
33951             .on('⇧←', pan([mapDimensions[0], 0]))
 
33952             .on('⇧↑', pan([0, mapDimensions[1]]))
 
33953             .on('⇧→', pan([-mapDimensions[0], 0]))
 
33954             .on('⇧↓', pan([0, -mapDimensions[1]]))
 
33955             .on(iD.ui.cmd('⌘←'), pan([mapDimensions[0], 0]))
 
33956             .on(iD.ui.cmd('⌘↑'), pan([0, mapDimensions[1]]))
 
33957             .on(iD.ui.cmd('⌘→'), pan([-mapDimensions[0], 0]))
 
33958             .on(iD.ui.cmd('⌘↓'), pan([0, -mapDimensions[1]]));
 
33960         d3.select(document)
 
33963         context.enter(iD.modes.Browse(context));
 
33965         context.container()
 
33966             .call(iD.ui.Splash(context))
 
33967             .call(iD.ui.Restore(context));
 
33969         var authenticating = iD.ui.Loading(context)
 
33970             .message(t('loading_auth'));
 
33972         context.connection()
 
33973             .on('authenticating.ui', function() {
 
33974                 context.container()
 
33975                     .call(authenticating);
 
33977             .on('authenticated.ui', function() {
 
33978                 authenticating.close();
 
33982     function ui(container) {
 
33983         context.container(container);
 
33984         context.loadLocale(function() {
 
33989     ui.sidebar = iD.ui.Sidebar(context);
 
33994 iD.ui.tooltipHtml = function(text, key) {
 
33995     var s = '<span>' + text + '</span>';
 
33997         s += '<div class="keyhint-wrap">' +
 
33998             '<span> ' + (t('tooltip_keyhint')) + ' </span>' +
 
33999             '<span class="keyhint"> ' + key + '</span></div>';
 
34003 iD.ui.Account = function(context) {
 
34004     var connection = context.connection();
 
34006     function update(selection) {
 
34007         if (!connection.authenticated()) {
 
34008             selection.selectAll('#userLink, #logoutLink')
 
34009                 .classed('hide', true);
 
34013         connection.userDetails(function(err, details) {
 
34014             var userLink = selection.select('#userLink'),
 
34015                 logoutLink = selection.select('#logoutLink');
 
34018             logoutLink.html('');
 
34022             selection.selectAll('#userLink, #logoutLink')
 
34023                 .classed('hide', false);
 
34026             userLink.append('a')
 
34027                 .attr('href', connection.userURL(details.display_name))
 
34028                 .attr('target', '_blank');
 
34030             // Add thumbnail or dont
 
34031             if (details.image_url) {
 
34032                 userLink.append('img')
 
34033                     .attr('class', 'icon pre-text user-icon')
 
34034                     .attr('src', details.image_url);
 
34037                     .call(iD.svg.Icon('#icon-avatar', 'pre-text light'));
 
34041             userLink.append('span')
 
34042                 .attr('class', 'label')
 
34043                 .text(details.display_name);
 
34045             logoutLink.append('a')
 
34046                 .attr('class', 'logout')
 
34049                 .on('click.logout', function() {
 
34050                     d3.event.preventDefault();
 
34051                     connection.logout();
 
34056     return function(selection) {
 
34057         selection.append('li')
 
34058             .attr('id', 'logoutLink')
 
34059             .classed('hide', true);
 
34061         selection.append('li')
 
34062             .attr('id', 'userLink')
 
34063             .classed('hide', true);
 
34065         connection.on('auth.account', function() { update(selection); });
 
34069 iD.ui.Attribution = function(context) {
 
34072     function attribution(data, klass) {
 
34073         var div = selection.selectAll('.' + klass)
 
34078             .attr('class', klass);
 
34080         var background = div.selectAll('.attribution')
 
34081             .data(data, function(d) { return d.name(); });
 
34085             .attr('class', 'attribution')
 
34086             .each(function(d) {
 
34087                 if (d.terms_html) {
 
34089                         .html(d.terms_html);
 
34093                 var source = d.terms_text || d.id || d.name();
 
34096                     source = '<img class="source-image" src="' + context.imagePath(d.logo) + '">';
 
34102                         .attr('href', d.terms_url)
 
34103                         .attr('target', '_blank')
 
34114         var copyright = background.selectAll('.copyright-notice')
 
34115             .data(function(d) {
 
34116                 var notice = d.copyrightNotices(context.map().zoom(), context.map().extent());
 
34117                 return notice ? [notice] : [];
 
34122             .attr('class', 'copyright-notice');
 
34124         copyright.text(String);
 
34130     function update() {
 
34131         attribution([context.background().baseLayerSource()], 'base-layer-attribution');
 
34132         attribution(context.background().overlayLayerSources().filter(function (s) {
 
34133             return s.validZoom(context.map().zoom());
 
34134         }), 'overlay-layer-attribution');
 
34137     return function(select) {
 
34138         selection = select;
 
34140         context.background()
 
34141             .on('change.attribution', update);
 
34144             .on('move.attribution', _.throttle(update, 400, {leading: false}));
 
34149 iD.ui.Background = function(context) {
 
34151         opacities = [1, 0.75, 0.5, 0.25],
 
34153             ['right', [0.5, 0]],
 
34154             ['top', [0, -0.5]],
 
34155             ['left', [-0.5, 0]],
 
34156             ['bottom', [0, 0.5]]],
 
34157         opacityDefault = (context.storage('background-opacity') !== null) ?
 
34158             (+context.storage('background-opacity')) : 1.0,
 
34159         customTemplate = context.storage('background-custom-template') || '',
 
34162     // Can be 0 from <1.3.0 use or due to issue #1923.
 
34163     if (opacityDefault === 0) opacityDefault = 1.0;
 
34166     function background(selection) {
 
34168         function sortSources(a, b) {
 
34169             return a.best() && !b.best() ? -1
 
34170                 : b.best() && !a.best() ? 1
 
34171                 : d3.descending(a.area(), b.area()) || d3.ascending(a.name(), b.name()) || 0;
 
34174         function setOpacity(d) {
 
34175             var bg = context.container().selectAll('.layer-background')
 
34177                 .style('opacity', d)
 
34178                 .attr('data-opacity', d);
 
34180             if (!iD.detect().opera) {
 
34181                 iD.util.setTransform(bg, 0, 0);
 
34184             opacityList.selectAll('li')
 
34185                 .classed('active', function(_) { return _ === d; });
 
34187             context.storage('background-opacity', d);
 
34190         function setTooltips(selection) {
 
34191             selection.each(function(d) {
 
34192                 var item = d3.select(this);
 
34193                 if (d === previous) {
 
34194                     item.call(bootstrap.tooltip()
 
34196                         .title(function() {
 
34197                             var tip = '<div>' + t('background.switch') + '</div>';
 
34198                             return iD.ui.tooltipHtml(tip, iD.ui.cmd('⌘B'));
 
34202                 } else if (d.description) {
 
34203                     item.call(bootstrap.tooltip()
 
34204                         .title(d.description)
 
34208                     item.call(bootstrap.tooltip().destroy);
 
34213         function selectLayer() {
 
34214             function active(d) {
 
34215                 return context.background().showsLayer(d);
 
34218             content.selectAll('.layer, .custom_layer')
 
34219                 .classed('active', active)
 
34220                 .classed('switch', function(d) { return d === previous; })
 
34222                 .selectAll('input')
 
34223                 .property('checked', active);
 
34226         function clickSetSource(d) {
 
34227             previous = context.background().baseLayerSource();
 
34228             d3.event.preventDefault();
 
34229             context.background().baseLayerSource(d);
 
34231             document.activeElement.blur();
 
34234         function editCustom() {
 
34235             d3.event.preventDefault();
 
34236             var template = window.prompt(t('background.custom_prompt'), customTemplate);
 
34238                 template.indexOf('google.com') !== -1 ||
 
34239                 template.indexOf('googleapis.com') !== -1 ||
 
34240                 template.indexOf('google.ru') !== -1) {
 
34244             setCustom(template);
 
34247         function setCustom(template) {
 
34248             context.background().baseLayerSource(iD.BackgroundSource.Custom(template));
 
34250             context.storage('background-custom-template', template);
 
34253         function clickSetOverlay(d) {
 
34254             d3.event.preventDefault();
 
34255             context.background().toggleOverlayLayer(d);
 
34257             document.activeElement.blur();
 
34260         function drawList(layerList, type, change, filter) {
 
34261             var sources = context.background()
 
34262                 .sources(context.map().extent())
 
34265             var layerLinks = layerList.selectAll('li.layer')
 
34266                 .data(sources, function(d) { return d.name(); });
 
34268             var enter = layerLinks.enter()
 
34269                 .insert('li', '.custom_layer')
 
34270                 .attr('class', 'layer')
 
34271                 .classed('best', function(d) { return d.best(); });
 
34273             enter.filter(function(d) { return d.best(); })
 
34275                 .attr('class', 'best')
 
34276                 .call(bootstrap.tooltip()
 
34277                     .title(t('background.best_imagery'))
 
34278                     .placement('left'))
 
34282             var label = enter.append('label');
 
34284             label.append('input')
 
34285                 .attr('type', type)
 
34286                 .attr('name', 'layers')
 
34287                 .on('change', change);
 
34289             label.append('span')
 
34290                 .text(function(d) { return d.name(); });
 
34296             layerList.selectAll('li.layer')
 
34298                 .style('display', layerList.selectAll('li.layer').data().length > 0 ? 'block' : 'none');
 
34301         function update() {
 
34302             backgroundList.call(drawList, 'radio', clickSetSource, function(d) { return !d.overlay; });
 
34303             overlayList.call(drawList, 'checkbox', clickSetOverlay, function(d) { return d.overlay; });
 
34307             var source = context.background().baseLayerSource();
 
34308             if (source.id === 'custom') {
 
34309                 customTemplate = source.template;
 
34315         function updateOffsetVal() {
 
34316             var meters = iD.geo.offsetToMeters(context.background().offset()),
 
34317                 x = +meters[0].toFixed(2),
 
34318                 y = +meters[1].toFixed(2);
 
34320             d3.selectAll('.nudge-inner-rect')
 
34322                 .classed('error', false)
 
34323                 .property('value', x + ', ' + y);
 
34325             d3.selectAll('.nudge-reset')
 
34326                 .classed('disabled', function() {
 
34327                     return (x === 0 && y === 0);
 
34331         function resetOffset() {
 
34332             context.background().offset([0, 0]);
 
34336         function nudge(d) {
 
34337             context.background().nudge(d, context.map().zoom());
 
34341         function buttonOffset(d) {
 
34342             var timeout = window.setTimeout(function() {
 
34343                     interval = window.setInterval(nudge.bind(null, d), 100);
 
34347             d3.select(window).on('mouseup', function() {
 
34348                 window.clearInterval(interval);
 
34349                 window.clearTimeout(timeout);
 
34350                 d3.select(window).on('mouseup', null);
 
34356         function inputOffset() {
 
34357             var input = d3.select(this);
 
34358             var d = input.node().value;
 
34360             if (d === '') return resetOffset();
 
34362             d = d.replace(/;/g, ',').split(',').map(function(n) {
 
34363                 // if n is NaN, it will always get mapped to false.
 
34364                 return !isNaN(n) && n;
 
34367             if (d.length !== 2 || !d[0] || !d[1]) {
 
34368                 input.classed('error', true);
 
34372             context.background().offset(iD.geo.metersToOffset(d));
 
34376         function dragOffset() {
 
34377             var origin = [d3.event.clientX, d3.event.clientY];
 
34379             context.container()
 
34381                 .attr('class', 'nudge-surface');
 
34384                 .on('mousemove.offset', function() {
 
34385                     var latest = [d3.event.clientX, d3.event.clientY];
 
34387                         -(origin[0] - latest[0]) / 4,
 
34388                         -(origin[1] - latest[1]) / 4
 
34394                 .on('mouseup.offset', function() {
 
34395                     d3.selectAll('.nudge-surface')
 
34399                         .on('mousemove.offset', null)
 
34400                         .on('mouseup.offset', null);
 
34403             d3.event.preventDefault();
 
34410         function toggle() {
 
34411             if (d3.event) d3.event.preventDefault();
 
34412             tooltip.hide(button);
 
34413             setVisible(!button.classed('active'));
 
34416         function quickSwitch() {
 
34418                 clickSetSource(previous);
 
34422         function setVisible(show) {
 
34423             if (show !== shown) {
 
34424                 button.classed('active', show);
 
34428                     selection.on('mousedown.background-inside', function() {
 
34429                         return d3.event.stopPropagation();
 
34431                     content.style('display', 'block')
 
34432                         .style('right', '-300px')
 
34435                         .style('right', '0px');
 
34437                     content.style('display', 'block')
 
34438                         .style('right', '0px')
 
34441                         .style('right', '-300px')
 
34442                         .each('end', function() {
 
34443                             d3.select(this).style('display', 'none');
 
34445                     selection.on('mousedown.background-inside', null);
 
34451         var content = selection.append('div')
 
34452                 .attr('class', 'fillL map-overlay col3 content hide'),
 
34453             tooltip = bootstrap.tooltip()
 
34456                 .title(iD.ui.tooltipHtml(t('background.description'), key)),
 
34457             button = selection.append('button')
 
34458                 .attr('tabindex', -1)
 
34459                 .on('click', toggle)
 
34460                 .call(iD.svg.Icon('#icon-layers', 'light'))
 
34465         /* opacity switcher */
 
34467         var opa = content.append('div')
 
34468                 .attr('class', 'opacity-options-wrapper');
 
34471             .text(t('background.title'));
 
34473         var opacityList = opa.append('ul')
 
34474             .attr('class', 'opacity-options');
 
34476         opacityList.selectAll('div.opacity')
 
34480             .attr('data-original-title', function(d) {
 
34481                 return t('background.percent_brightness', { opacity: (d * 100) });
 
34483             .on('click.set-opacity', setOpacity)
 
34484             .html('<div class="select-box"></div>')
 
34485             .call(bootstrap.tooltip()
 
34486                 .placement('left'))
 
34488             .attr('class', 'opacity')
 
34489             .style('opacity', function(d) { return 1.25 - d; });
 
34492         /* background switcher */
 
34494         var backgroundList = content.append('ul')
 
34495             .attr('class', 'layer-list');
 
34497         var custom = backgroundList.append('li')
 
34498             .attr('class', 'custom_layer')
 
34499             .datum(iD.BackgroundSource.Custom());
 
34501         custom.append('button')
 
34502             .attr('class', 'layer-browse')
 
34503             .call(bootstrap.tooltip()
 
34504                 .title(t('background.custom_button'))
 
34505                 .placement('left'))
 
34506             .on('click', editCustom)
 
34507             .call(iD.svg.Icon('#icon-search'));
 
34509         var label = custom.append('label');
 
34511         label.append('input')
 
34512             .attr('type', 'radio')
 
34513             .attr('name', 'layers')
 
34514             .on('change', function () {
 
34515                 if (customTemplate) {
 
34516                     setCustom(customTemplate);
 
34522         label.append('span')
 
34523             .text(t('background.custom'));
 
34525         content.append('div')
 
34526             .attr('class', 'imagery-faq')
 
34528             .attr('target', '_blank')
 
34529             .attr('tabindex', -1)
 
34530             .call(iD.svg.Icon('#icon-out-link', 'inline'))
 
34531             .attr('href', 'https://github.com/openstreetmap/iD/blob/master/FAQ.md#how-can-i-report-an-issue-with-background-imagery')
 
34533             .text(t('background.imagery_source_faq'));
 
34535         var overlayList = content.append('ul')
 
34536             .attr('class', 'layer-list');
 
34538         var controls = content.append('div')
 
34539             .attr('class', 'controls-list');
 
34542         /* minimap toggle */
 
34544         var minimapLabel = controls
 
34546             .call(bootstrap.tooltip()
 
34548                 .title(iD.ui.tooltipHtml(t('background.minimap.tooltip'), '/'))
 
34552         minimapLabel.classed('minimap-toggle', true)
 
34554             .attr('type', 'checkbox')
 
34555             .on('change', function() {
 
34556                 iD.ui.MapInMap.toggle();
 
34557                 d3.event.preventDefault();
 
34560         minimapLabel.append('span')
 
34561             .text(t('background.minimap.description'));
 
34564         /* imagery offset controls */
 
34566         var adjustments = content.append('div')
 
34567             .attr('class', 'adjustments');
 
34569         adjustments.append('a')
 
34570             .text(t('background.fix_misalignment'))
 
34572             .classed('hide-toggle', true)
 
34573             .classed('expanded', false)
 
34574             .on('click', function() {
 
34575                 var exp = d3.select(this).classed('expanded');
 
34576                 nudgeContainer.style('display', exp ? 'none' : 'block');
 
34577                 d3.select(this).classed('expanded', !exp);
 
34578                 d3.event.preventDefault();
 
34581         var nudgeContainer = adjustments.append('div')
 
34582             .attr('class', 'nudge-container cf')
 
34583             .style('display', 'none');
 
34585         nudgeContainer.append('div')
 
34586             .attr('class', 'nudge-instructions')
 
34587             .text(t('background.offset'));
 
34589         var nudgeRect = nudgeContainer.append('div')
 
34590             .attr('class', 'nudge-outer-rect')
 
34591             .on('mousedown', dragOffset);
 
34593         nudgeRect.append('div')
 
34594             .attr('class', 'nudge-inner-rect')
 
34596             .on('change', inputOffset)
 
34597             .on('mousedown', function() {
 
34598                 d3.event.stopPropagation();
 
34601         nudgeContainer.append('div')
 
34602             .selectAll('button')
 
34603             .data(directions).enter()
 
34605             .attr('class', function(d) { return d[0] + ' nudge'; })
 
34606             .on('mousedown', function(d) {
 
34607                 buttonOffset(d[1]);
 
34610         nudgeContainer.append('button')
 
34611             .attr('title', t('background.reset'))
 
34612             .attr('class', 'nudge-reset disabled')
 
34613             .on('click', resetOffset)
 
34614             .call(iD.svg.Icon('#icon-undo'));
 
34617             .on('move.background-update', _.debounce(update, 1000));
 
34619         context.background()
 
34620             .on('change.background-update', update);
 
34624         setOpacity(opacityDefault);
 
34626         var keybinding = d3.keybinding('background')
 
34628             .on(iD.ui.cmd('⌘B'), quickSwitch)
 
34632         d3.select(document)
 
34635         context.surface().on('mousedown.background-outside', hide);
 
34636         context.container().on('mousedown.background-outside', hide);
 
34641 // Translate a MacOS key command into the appropriate Windows/Linux equivalent.
 
34642 // For example, ⌘Z -> Ctrl+Z
 
34643 iD.ui.cmd = function(code) {
 
34644     if (iD.detect().os === 'mac') {
 
34648     if (iD.detect().os === 'win') {
 
34649         if (code === '⌘⇧Z') return 'Ctrl+Y';
 
34661     for (var i = 0; i < code.length; i++) {
 
34662         if (code[i] in replacements) {
 
34663             result += replacements[code[i]] + '+';
 
34671 iD.ui.Commit = function(context) {
 
34672     var dispatch = d3.dispatch('cancel', 'save');
 
34674     function commit(selection) {
 
34675         var changes = context.history().changes(),
 
34676             summary = context.history().difference().summary();
 
34678         function zoomToEntity(change) {
 
34679             var entity = change.entity;
 
34680             if (change.changeType !== 'deleted' &&
 
34681                 context.graph().entity(entity.id).geometry(context.graph()) !== 'vertex') {
 
34682                 context.map().zoomTo(entity);
 
34683                 context.surface().selectAll(
 
34684                     iD.util.entityOrMemberSelector([entity.id], context.graph()))
 
34685                     .classed('hover', true);
 
34689         var header = selection.append('div')
 
34690             .attr('class', 'header fillL');
 
34692         header.append('h3')
 
34693             .text(t('commit.title'));
 
34695         var body = selection.append('div')
 
34696             .attr('class', 'body');
 
34700         var commentSection = body.append('div')
 
34701             .attr('class', 'modal-section form-field commit-form');
 
34703         commentSection.append('label')
 
34704             .attr('class', 'form-label')
 
34705             .text(t('commit.message_label'));
 
34707         var commentField = commentSection.append('textarea')
 
34708             .attr('placeholder', t('commit.description_placeholder'))
 
34709             .attr('maxlength', 255)
 
34710             .property('value', context.storage('comment') || '')
 
34711             .on('input.save', checkComment)
 
34712             .on('change.save', checkComment)
 
34713             .on('blur.save', function() {
 
34714                 context.storage('comment', this.value);
 
34717         function checkComment() {
 
34718             d3.selectAll('.save-section .save-button')
 
34719                 .attr('disabled', (this.value.length ? null : true));
 
34721             var googleWarning = clippyArea
 
34724                .data(this.value.match(/google/i) ? [true] : []);
 
34726             googleWarning.exit().remove();
 
34728             googleWarning.enter()
 
34730                .attr('target', '_blank')
 
34731                .attr('tabindex', -1)
 
34732                .call(iD.svg.Icon('#icon-alert', 'inline'))
 
34733                .attr('href', t('commit.google_warning_link'))
 
34735                .text(t('commit.google_warning'));
 
34738         commentField.node().select();
 
34740         context.connection().userChangesets(function (err, changesets) {
 
34745             for (var i = 0; i < changesets.length; i++) {
 
34746                 if (changesets[i].tags.comment) {
 
34748                         title: changesets[i].tags.comment,
 
34749                         value: changesets[i].tags.comment
 
34754             commentField.call(d3.combobox().caseSensitive(true).data(comments));
 
34757         var clippyArea = commentSection.append('div')
 
34758             .attr('class', 'clippy-area');
 
34761         var changeSetInfo = commentSection.append('div')
 
34762             .attr('class', 'changeset-info');
 
34764         changeSetInfo.append('a')
 
34765             .attr('target', '_blank')
 
34766             .attr('tabindex', -1)
 
34767             .call(iD.svg.Icon('#icon-out-link', 'inline'))
 
34768             .attr('href', t('commit.about_changeset_comments_link'))
 
34770             .text(t('commit.about_changeset_comments'));
 
34773         var warnings = body.selectAll('div.warning-section')
 
34774             .data([context.history().validate(changes)])
 
34777             .attr('class', 'modal-section warning-section fillL2')
 
34778             .style('display', function(d) { return _.isEmpty(d) ? 'none' : null; })
 
34779             .style('background', '#ffb');
 
34781         warnings.append('h3')
 
34782             .text(t('commit.warnings'));
 
34784         var warningLi = warnings.append('ul')
 
34785             .attr('class', 'changeset-list')
 
34787             .data(function(d) { return d; })
 
34791             .on('mouseover', mouseover)
 
34792             .on('mouseout', mouseout)
 
34793             .on('click', warningClick);
 
34796             .call(iD.svg.Icon('#icon-alert', 'pre-text'));
 
34799             .append('strong').text(function(d) {
 
34803         warningLi.filter(function(d) { return d.tooltip; })
 
34804             .call(bootstrap.tooltip()
 
34805                 .title(function(d) { return d.tooltip; })
 
34810         // Upload Explanation
 
34811         var saveSection = body.append('div')
 
34812             .attr('class','modal-section save-section fillL cf');
 
34814         var prose = saveSection.append('p')
 
34815             .attr('class', 'commit-info')
 
34816             .html(t('commit.upload_explanation'));
 
34818         context.connection().userDetails(function(err, user) {
 
34821             var userLink = d3.select(document.createElement('div'));
 
34823             if (user.image_url) {
 
34824                 userLink.append('img')
 
34825                     .attr('src', user.image_url)
 
34826                     .attr('class', 'icon pre-text user-icon');
 
34829             userLink.append('a')
 
34830                 .attr('class','user-info')
 
34831                 .text(user.display_name)
 
34832                 .attr('href', context.connection().userURL(user.display_name))
 
34833                 .attr('tabindex', -1)
 
34834                 .attr('target', '_blank');
 
34836             prose.html(t('commit.upload_explanation_with_user', {user: userLink.html()}));
 
34841         var buttonSection = saveSection.append('div')
 
34842             .attr('class','buttons fillL cf');
 
34844         var cancelButton = buttonSection.append('button')
 
34845             .attr('class', 'secondary-action col5 button cancel-button')
 
34846             .on('click.cancel', function() { dispatch.cancel(); });
 
34848         cancelButton.append('span')
 
34849             .attr('class', 'label')
 
34850             .text(t('commit.cancel'));
 
34852         var saveButton = buttonSection.append('button')
 
34853             .attr('class', 'action col5 button save-button')
 
34854             .attr('disabled', function() {
 
34855                 var n = d3.select('.commit-form textarea').node();
 
34856                 return (n && n.value.length) ? null : true;
 
34858             .on('click.save', function() {
 
34860                     comment: commentField.node().value
 
34864         saveButton.append('span')
 
34865             .attr('class', 'label')
 
34866             .text(t('commit.save'));
 
34870         var changeSection = body.selectAll('div.commit-section')
 
34874             .attr('class', 'commit-section modal-section fillL2');
 
34876         changeSection.append('h3')
 
34877             .text(t('commit.changes', {count: summary.length}));
 
34879         var li = changeSection.append('ul')
 
34880             .attr('class', 'changeset-list')
 
34885             .on('mouseover', mouseover)
 
34886             .on('mouseout', mouseout)
 
34887             .on('click', zoomToEntity);
 
34889         li.each(function(d) {
 
34891                 .call(iD.svg.Icon('#icon-' + d.entity.geometry(d.graph), 'pre-text ' + d.changeType));
 
34895             .attr('class', 'change-type')
 
34896             .text(function(d) {
 
34897                 return t('commit.' + d.changeType) + ' ';
 
34900         li.append('strong')
 
34901             .attr('class', 'entity-type')
 
34902             .text(function(d) {
 
34903                 return context.presets().match(d.entity, d.graph).name();
 
34907             .attr('class', 'entity-name')
 
34908             .text(function(d) {
 
34909                 var name = iD.util.displayName(d.entity) || '',
 
34911                 if (name !== '') string += ':';
 
34912                 return string += ' ' + name;
 
34915         li.style('opacity', 0)
 
34917             .style('opacity', 1);
 
34920         function mouseover(d) {
 
34922                 context.surface().selectAll(
 
34923                     iD.util.entityOrMemberSelector([d.entity.id], context.graph())
 
34924                 ).classed('hover', true);
 
34928         function mouseout() {
 
34929             context.surface().selectAll('.hover')
 
34930                 .classed('hover', false);
 
34933         function warningClick(d) {
 
34935                 context.map().zoomTo(d.entity);
 
34937                     iD.modes.Select(context, [d.entity.id])
 
34938                         .suppressMenu(true));
 
34942         // Call checkComment off the bat, in case a changeset
 
34943         // comment is recovered from localStorage
 
34944         commentField.trigger('input');
 
34947     return d3.rebind(commit, dispatch, 'on');
 
34949 iD.ui.confirm = function(selection) {
 
34950     var modal = iD.ui.modal(selection);
 
34952     modal.select('.modal')
 
34953         .classed('modal-alert', true);
 
34955     var section = modal.select('.content');
 
34957     section.append('div')
 
34958         .attr('class', 'modal-section header');
 
34960     section.append('div')
 
34961         .attr('class', 'modal-section message-text');
 
34963     var buttons = section.append('div')
 
34964         .attr('class', 'modal-section buttons cf');
 
34966     modal.okButton = function() {
 
34969             .attr('class', 'action col4')
 
34970             .on('click.confirm', function() {
 
34973             .text(t('confirm.okay'));
 
34980 iD.ui.Conflicts = function(context) {
 
34981     var dispatch = d3.dispatch('download', 'cancel', 'save'),
 
34984     function conflicts(selection) {
 
34985         var header = selection
 
34987             .attr('class', 'header fillL');
 
34991             .attr('class', 'fr')
 
34992             .on('click', function() { dispatch.cancel(); })
 
34993             .call(iD.svg.Icon('#icon-close'));
 
34997             .text(t('save.conflict.header'));
 
34999         var body = selection
 
35001             .attr('class', 'body fillL');
 
35005             .attr('class', 'conflicts-help')
 
35006             .text(t('save.conflict.help'))
 
35008             .attr('class', 'conflicts-download')
 
35009             .text(t('save.conflict.download_changes'))
 
35010             .on('click.download', function() { dispatch.download(); });
 
35014             .attr('class', 'conflict-container fillL3')
 
35015             .call(showConflict, 0);
 
35019             .attr('class', 'conflicts-done')
 
35020             .attr('opacity', 0)
 
35021             .style('display', 'none')
 
35022             .text(t('save.conflict.done'));
 
35026             .attr('class','buttons col12 joined conflicts-buttons');
 
35030             .attr('disabled', list.length > 1)
 
35031             .attr('class', 'action conflicts-button col6')
 
35032             .text(t('save.title'))
 
35033             .on('click.try_again', function() { dispatch.save(); });
 
35037             .attr('class', 'secondary-action conflicts-button col6')
 
35038             .text(t('confirm.cancel'))
 
35039             .on('click.cancel', function() { dispatch.cancel(); });
 
35043     function showConflict(selection, index) {
 
35044         if (index < 0 || index >= list.length) return;
 
35046         var parent = d3.select(selection.node().parentNode);
 
35048         // enable save button if this is the last conflict being reviewed..
 
35049         if (index === list.length - 1) {
 
35050             window.setTimeout(function() {
 
35051                 parent.select('.conflicts-button')
 
35052                     .attr('disabled', null);
 
35054                 parent.select('.conflicts-done')
 
35056                     .attr('opacity', 1)
 
35057                     .style('display', 'block');
 
35061         var item = selection
 
35062             .selectAll('.conflict')
 
35063             .data([list[index]]);
 
35065         var enter = item.enter()
 
35067             .attr('class', 'conflict');
 
35071             .attr('class', 'conflict-count')
 
35072             .text(t('save.conflict.count', { num: index + 1, total: list.length }));
 
35076             .attr('class', 'conflict-description')
 
35078             .text(function(d) { return d.name; })
 
35079             .on('click', function(d) {
 
35080                 zoomToEntity(d.id);
 
35081                 d3.event.preventDefault();
 
35084         var details = enter
 
35086             .attr('class', 'conflict-detail-container');
 
35090             .attr('class', 'conflict-detail-list')
 
35092             .data(function(d) { return d.details || []; })
 
35095             .attr('class', 'conflict-detail-item')
 
35096             .html(function(d) { return d; });
 
35100             .attr('class', 'conflict-choices')
 
35105             .attr('class', 'conflict-nav-buttons joined cf')
 
35106             .selectAll('button')
 
35107             .data(['previous', 'next'])
 
35110             .text(function(d) { return t('save.conflict.' + d); })
 
35111             .attr('class', 'conflict-nav-button action col6')
 
35112             .attr('disabled', function(d, i) {
 
35113                 return (i === 0 && index === 0) ||
 
35114                     (i === 1 && index === list.length - 1) || null;
 
35116             .on('click', function(d, i) {
 
35117                 var container = parent.select('.conflict-container'),
 
35118                 sign = (i === 0 ? -1 : 1);
 
35121                     .selectAll('.conflict')
 
35125                     .call(showConflict, index + sign);
 
35127                 d3.event.preventDefault();
 
35135     function addChoices(selection) {
 
35136         var choices = selection
 
35138             .attr('class', 'layer-list')
 
35140             .data(function(d) { return d.choices || []; });
 
35142         var enter = choices.enter()
 
35144             .attr('class', 'layer');
 
35151             .attr('type', 'radio')
 
35152             .attr('name', function(d) { return d.id; })
 
35153             .on('change', function(d, i) {
 
35154                 var ul = this.parentNode.parentNode.parentNode;
 
35155                 ul.__data__.chosen = i;
 
35161             .text(function(d) { return d.text; });
 
35164             .each(function(d, i) {
 
35165                 var ul = this.parentNode;
 
35166                 if (ul.__data__.chosen === i) choose(ul, d);
 
35170     function choose(ul, datum) {
 
35171         if (d3.event) d3.event.preventDefault();
 
35175             .classed('active', function(d) { return d === datum; })
 
35176             .selectAll('input')
 
35177             .property('checked', function(d) { return d === datum; });
 
35179         var extent = iD.geo.Extent(),
 
35182         entity = context.graph().hasEntity(datum.id);
 
35183         if (entity) extent._extend(entity.extent(context.graph()));
 
35187         entity = context.graph().hasEntity(datum.id);
 
35188         if (entity) extent._extend(entity.extent(context.graph()));
 
35190         zoomToEntity(datum.id, extent);
 
35193     function zoomToEntity(id, extent) {
 
35194         context.surface().selectAll('.hover')
 
35195             .classed('hover', false);
 
35197         var entity = context.graph().hasEntity(id);
 
35200                 context.map().trimmedExtent(extent);
 
35202                 context.map().zoomTo(entity);
 
35204             context.surface().selectAll(
 
35205                 iD.util.entityOrMemberSelector([entity.id], context.graph()))
 
35206                 .classed('hover', true);
 
35211     // The conflict list should be an array of objects like:
 
35214     //     name: entityName(local),
 
35215     //     details: merge.conflicts(),
 
35218     //         choice(id, keepMine, forceLocal),
 
35219     //         choice(id, keepTheirs, forceRemote)
 
35222     conflicts.list = function(_) {
 
35223         if (!arguments.length) return list;
 
35228     return d3.rebind(conflicts, dispatch, 'on');
 
35230 iD.ui.Contributors = function(context) {
 
35231     var debouncedUpdate = _.debounce(function() { update(); }, 1000),
 
35234         wrap = d3.select(null);
 
35236     function update() {
 
35238             entities = context.intersects(context.map().extent());
 
35240         entities.forEach(function(entity) {
 
35241             if (entity && entity.user) users[entity.user] = true;
 
35244         var u = Object.keys(users),
 
35245             subset = u.slice(0, u.length > limit ? limit - 1 : limit);
 
35248             .call(iD.svg.Icon('#icon-nearby', 'pre-text light'));
 
35250         var userList = d3.select(document.createElement('span'));
 
35252         userList.selectAll()
 
35256             .attr('class', 'user-link')
 
35257             .attr('href', function(d) { return context.connection().userURL(d); })
 
35258             .attr('target', '_blank')
 
35259             .attr('tabindex', -1)
 
35262         if (u.length > limit) {
 
35263             var count = d3.select(document.createElement('span'));
 
35266                 .attr('target', '_blank')
 
35267                 .attr('tabindex', -1)
 
35268                 .attr('href', function() {
 
35269                     return context.connection().changesetsURL(context.map().center(), context.map().zoom());
 
35271                 .text(u.length - limit + 1);
 
35273             wrap.append('span')
 
35274                 .html(t('contributors.truncated_list', { users: userList.html(), count: count.html() }));
 
35277             wrap.append('span')
 
35278                 .html(t('contributors.list', { users: userList.html() }));
 
35285                 .style('opacity', 0);
 
35287         } else if (hidden) {
 
35290                 .style('opacity', 1);
 
35294     return function(selection) {
 
35298         context.connection().on('loaded.contributors', debouncedUpdate);
 
35299         context.map().on('move.contributors', debouncedUpdate);
 
35302 iD.ui.Disclosure = function() {
 
35303     var dispatch = d3.dispatch('toggled'),
 
35306         content = function () {};
 
35308     var disclosure = function(selection) {
 
35309         var $link = selection.selectAll('.hide-toggle')
 
35312         $link.enter().append('a')
 
35314             .attr('class', 'hide-toggle');
 
35317             .on('click', toggle)
 
35318             .classed('expanded', expanded);
 
35320         var $body = selection.selectAll('div')
 
35323         $body.enter().append('div');
 
35325         $body.classed('hide', !expanded)
 
35328         function toggle() {
 
35329             expanded = !expanded;
 
35330             $link.classed('expanded', expanded);
 
35331             $body.call(iD.ui.Toggle(expanded));
 
35332             dispatch.toggled(expanded);
 
35336     disclosure.title = function(_) {
 
35337         if (!arguments.length) return title;
 
35342     disclosure.expanded = function(_) {
 
35343         if (!arguments.length) return expanded;
 
35348     disclosure.content = function(_) {
 
35349         if (!arguments.length) return content;
 
35354     return d3.rebind(disclosure, dispatch, 'on');
 
35356 iD.ui.EntityEditor = function(context) {
 
35357     var dispatch = d3.dispatch('choose'),
 
35359         coalesceChanges = false,
 
35366     var presetEditor = iD.ui.preset(context)
 
35367         .on('change', changeTags);
 
35368     var rawTagEditor = iD.ui.RawTagEditor(context)
 
35369         .on('change', changeTags);
 
35371     function entityEditor(selection) {
 
35372         var entity = context.entity(id),
 
35373             tags = _.clone(entity.tags);
 
35375         var $header = selection.selectAll('.header')
 
35379         var $enter = $header.enter().append('div')
 
35380             .attr('class', 'header fillL cf');
 
35382         $enter.append('button')
 
35383             .attr('class', 'fl preset-reset preset-choose')
 
35387         $enter.append('button')
 
35388             .attr('class', 'fr preset-close')
 
35389             .call(iD.svg.Icon(modified ? '#icon-apply' : '#icon-close'));
 
35391         $enter.append('h3');
 
35394         $header.select('h3')
 
35395             .text(t('inspector.edit'));
 
35397         $header.select('.preset-close')
 
35398             .on('click', function() {
 
35399                 context.enter(iD.modes.Browse(context));
 
35402         var $body = selection.selectAll('.inspector-body')
 
35406         $enter = $body.enter().append('div')
 
35407             .attr('class', 'inspector-body');
 
35409         $enter.append('div')
 
35410             .attr('class', 'preset-list-item inspector-inner')
 
35412             .attr('class', 'preset-list-button-wrap')
 
35414             .attr('class', 'preset-list-button preset-reset')
 
35415             .call(bootstrap.tooltip()
 
35416                 .title(t('inspector.back_tooltip'))
 
35417                 .placement('bottom'))
 
35419             .attr('class', 'label');
 
35421         $body.select('.preset-list-button-wrap')
 
35422             .call(reference.button);
 
35424         $body.select('.preset-list-item')
 
35425             .call(reference.body);
 
35427         $enter.append('div')
 
35428             .attr('class', 'inspector-border inspector-preset');
 
35430         $enter.append('div')
 
35431             .attr('class', 'inspector-border raw-tag-editor inspector-inner');
 
35433         $enter.append('div')
 
35434             .attr('class', 'inspector-border raw-member-editor inspector-inner');
 
35436         $enter.append('div')
 
35437             .attr('class', 'raw-membership-editor inspector-inner');
 
35439         selection.selectAll('.preset-reset')
 
35440             .on('click', function() {
 
35441                 dispatch.choose(preset);
 
35445         $body.select('.preset-list-item button')
 
35446             .call(iD.ui.PresetIcon()
 
35447                 .geometry(context.geometry(id))
 
35450         $body.select('.preset-list-item .label')
 
35451             .text(preset.name());
 
35453         $body.select('.inspector-preset')
 
35460         $body.select('.raw-tag-editor')
 
35467         if (entity.type === 'relation') {
 
35468             $body.select('.raw-member-editor')
 
35469                 .style('display', 'block')
 
35470                 .call(iD.ui.RawMemberEditor(context)
 
35473             $body.select('.raw-member-editor')
 
35474                 .style('display', 'none');
 
35477         $body.select('.raw-membership-editor')
 
35478             .call(iD.ui.RawMembershipEditor(context)
 
35481         function historyChanged() {
 
35482             if (state === 'hide') return;
 
35484             var entity = context.hasEntity(id),
 
35485                 graph = context.graph();
 
35486             if (!entity) return;
 
35488             entityEditor.preset(context.presets().match(entity, graph));
 
35489             entityEditor.modified(base !== graph);
 
35490             entityEditor(selection);
 
35494             .on('change.entity-editor', historyChanged);
 
35497     function clean(o) {
 
35499         function cleanVal(k, v) {
 
35500             function keepSpaces(k) {
 
35501                 var whitelist = ['opening_hours', 'service_times', 'collection_times',
 
35502                     'operating_times', 'smoking_hours', 'happy_hours'];
 
35503                 return _.some(whitelist, function(s) { return k.indexOf(s) !== -1; });
 
35506             var blacklist = ['description', 'note', 'fixme'];
 
35507             if (_.some(blacklist, function(s) { return k.indexOf(s) !== -1; })) return v;
 
35509             var cleaned = v.split(';')
 
35510                 .map(function(s) { return s.trim(); })
 
35511                 .join(keepSpaces(k) ? '; ' : ';');
 
35513             // The code below is not intended to validate websites and emails.
 
35514             // It is only intended to prevent obvious copy-paste errors. (#2323)
 
35516             // clean website- and email-like tags
 
35517             if (k.indexOf('website') !== -1 ||
 
35518                 k.indexOf('email') !== -1 ||
 
35519                 cleaned.indexOf('http') === 0) {
 
35521                     .replace(/[\u200B-\u200F\uFEFF]/g, '');  // strip LRM and other zero width chars
 
35528         var out = {}, k, v;
 
35530             if (k && (v = o[k]) !== undefined) {
 
35531                 out[k] = cleanVal(k, v);
 
35537     // Tag changes that fire on input can all get coalesced into a single
 
35538     // history operation when the user leaves the field.  #2342
 
35539     function changeTags(changed, onInput) {
 
35540         var entity = context.entity(id),
 
35541             annotation = t('operations.change_tags.annotation'),
 
35542             tags = _.extend({}, entity.tags, changed);
 
35545             tags = clean(tags);
 
35547         if (!_.isEqual(entity.tags, tags)) {
 
35548             if (coalesceChanges) {
 
35549                 context.overwrite(iD.actions.ChangeTags(id, tags), annotation);
 
35551                 context.perform(iD.actions.ChangeTags(id, tags), annotation);
 
35552                 coalesceChanges = !!onInput;
 
35557     entityEditor.modified = function(_) {
 
35558         if (!arguments.length) return modified;
 
35560         d3.selectAll('button.preset-close use')
 
35561             .attr('xlink:href', (modified ? '#icon-apply' : '#icon-close'));
 
35564     entityEditor.state = function(_) {
 
35565         if (!arguments.length) return state;
 
35567         return entityEditor;
 
35570     entityEditor.entityID = function(_) {
 
35571         if (!arguments.length) return id;
 
35573         base = context.graph();
 
35574         entityEditor.preset(context.presets().match(context.entity(id), base));
 
35575         entityEditor.modified(false);
 
35576         coalesceChanges = false;
 
35577         return entityEditor;
 
35580     entityEditor.preset = function(_) {
 
35581         if (!arguments.length) return preset;
 
35582         if (_ !== preset) {
 
35584             reference = iD.ui.TagReference(preset.reference(context.geometry(id)), context)
 
35587         return entityEditor;
 
35590     return d3.rebind(entityEditor, dispatch, 'on');
 
35592 iD.ui.FeatureInfo = function(context) {
 
35593     function update(selection) {
 
35594         var features = context.features(),
 
35595             stats = features.stats(),
 
35597             hiddenList = _.compact(_.map(features.hidden(), function(k) {
 
35600                     return String(stats[k]) + ' ' + t('feature.' + k + '.description');
 
35604         selection.html('');
 
35606         if (hiddenList.length) {
 
35607             var tooltip = bootstrap.tooltip()
 
35610                     .title(function() {
 
35611                         return iD.ui.tooltipHtml(hiddenList.join('<br/>'));
 
35614             var warning = selection.append('a')
 
35616                 .attr('tabindex', -1)
 
35617                 .html(t('feature_info.hidden_warning', { count: count }))
 
35619                 .on('click', function() {
 
35620                     tooltip.hide(warning);
 
35621                     // open map data panel?
 
35622                     d3.event.preventDefault();
 
35627             .classed('hide', !hiddenList.length);
 
35630     return function(selection) {
 
35633         context.features().on('change.feature_info', function() {
 
35638 iD.ui.FeatureList = function(context) {
 
35639     var geocodeResults;
 
35641     function featureList(selection) {
 
35642         var header = selection.append('div')
 
35643             .attr('class', 'header fillL cf');
 
35645         header.append('h3')
 
35646             .text(t('inspector.feature_list'));
 
35648         function keypress() {
 
35649             var q = search.property('value'),
 
35650                 items = list.selectAll('.feature-list-item');
 
35651             if (d3.event.keyCode === 13 && q.length && items.size()) {
 
35652                 click(items.datum());
 
35656         function inputevent() {
 
35657             geocodeResults = undefined;
 
35661         var searchWrap = selection.append('div')
 
35662             .attr('class', 'search-header');
 
35664         var search = searchWrap.append('input')
 
35665             .attr('placeholder', t('inspector.search'))
 
35666             .attr('type', 'search')
 
35667             .on('keypress', keypress)
 
35668             .on('input', inputevent);
 
35671             .call(iD.svg.Icon('#icon-search', 'pre-text'));
 
35673         var listWrap = selection.append('div')
 
35674             .attr('class', 'inspector-body');
 
35676         var list = listWrap.append('div')
 
35677             .attr('class', 'feature-list cf');
 
35680             .on('exit.feature-list', clearSearch);
 
35682             .on('drawn.feature-list', mapDrawn);
 
35684         function clearSearch() {
 
35685             search.property('value', '');
 
35689         function mapDrawn(e) {
 
35695         function features() {
 
35698                 graph = context.graph(),
 
35699                 q = search.property('value').toLowerCase();
 
35701             if (!q) return result;
 
35703             var idMatch = q.match(/^([nwr])([0-9]+)$/);
 
35708                     geometry: idMatch[1] === 'n' ? 'point' : idMatch[1] === 'w' ? 'line' : 'relation',
 
35709                     type: idMatch[1] === 'n' ? t('inspector.node') : idMatch[1] === 'w' ? t('inspector.way') : t('inspector.relation'),
 
35714             var locationMatch = sexagesimal.pair(q.toUpperCase()) || q.match(/^(-?\d+\.?\d*)\s+(-?\d+\.?\d*)$/);
 
35716             if (locationMatch) {
 
35717                 var loc = [parseFloat(locationMatch[0]), parseFloat(locationMatch[1])];
 
35721                     type: t('inspector.location'),
 
35722                     name: loc[0].toFixed(6) + ', ' + loc[1].toFixed(6),
 
35727             function addEntity(entity) {
 
35728                 if (entity.id in entities || result.length > 200)
 
35731                 entities[entity.id] = true;
 
35733                 var name = iD.util.displayName(entity) || '';
 
35734                 if (name.toLowerCase().indexOf(q) >= 0) {
 
35738                         geometry: context.geometry(entity.id),
 
35739                         type: context.presets().match(entity, graph).name(),
 
35744                 graph.parentRelations(entity).forEach(function(parent) {
 
35749             var visible = context.surface().selectAll('.point, .line, .area')[0];
 
35750             for (var i = 0; i < visible.length && result.length <= 200; i++) {
 
35751                 addEntity(visible[i].__data__);
 
35754             (geocodeResults || []).forEach(function(d) {
 
35755                 // https://github.com/openstreetmap/iD/issues/1890
 
35756                 if (d.osm_type && d.osm_id) {
 
35758                         id: iD.Entity.id.fromOSM(d.osm_type, d.osm_id),
 
35759                         geometry: d.osm_type === 'relation' ? 'relation' : d.osm_type === 'way' ? 'line' : 'point',
 
35760                         type: d.type !== 'yes' ? (d.type.charAt(0).toUpperCase() + d.type.slice(1)).replace('_', ' ')
 
35761                                                : (d.class.charAt(0).toUpperCase() + d.class.slice(1)).replace('_', ' '),
 
35762                         name: d.display_name,
 
35763                         extent: new iD.geo.Extent(
 
35764                             [parseFloat(d.boundingbox[3]), parseFloat(d.boundingbox[0])],
 
35765                             [parseFloat(d.boundingbox[2]), parseFloat(d.boundingbox[1])])
 
35773         function drawList() {
 
35774             var value = search.property('value'),
 
35775                 results = features();
 
35777             list.classed('filtered', value.length);
 
35779             var noResultsWorldwide = geocodeResults && geocodeResults.length === 0;
 
35781             var resultsIndicator = list.selectAll('.no-results-item')
 
35783                 .enter().append('button')
 
35784                 .property('disabled', true)
 
35785                 .attr('class', 'no-results-item')
 
35786                 .call(iD.svg.Icon('#icon-alert', 'pre-text'));
 
35788             resultsIndicator.append('span')
 
35789                 .attr('class', 'entity-name');
 
35791             list.selectAll('.no-results-item .entity-name')
 
35792                 .text(noResultsWorldwide ? t('geocoder.no_results_worldwide') : t('geocoder.no_results_visible'));
 
35794             list.selectAll('.geocode-item')
 
35796                 .enter().append('button')
 
35797                 .attr('class', 'geocode-item')
 
35798                 .on('click', geocode)
 
35800                 .attr('class', 'label')
 
35802                 .attr('class', 'entity-name')
 
35803                 .text(t('geocoder.search'));
 
35805             list.selectAll('.no-results-item')
 
35806                 .style('display', (value.length && !results.length) ? 'block' : 'none');
 
35808             list.selectAll('.geocode-item')
 
35809                 .style('display', (value && geocodeResults === undefined) ? 'block' : 'none');
 
35811             list.selectAll('.feature-list-item')
 
35815             var items = list.selectAll('.feature-list-item')
 
35816                 .data(results, function(d) { return d.id; });
 
35818             var enter = items.enter()
 
35819                 .insert('button', '.geocode-item')
 
35820                 .attr('class', 'feature-list-item')
 
35821                 .on('mouseover', mouseover)
 
35822                 .on('mouseout', mouseout)
 
35823                 .on('click', click);
 
35827                 .attr('class', 'label');
 
35829             label.each(function(d) {
 
35831                     .call(iD.svg.Icon('#icon-' + d.geometry, 'pre-text'));
 
35834             label.append('span')
 
35835                 .attr('class', 'entity-type')
 
35836                 .text(function(d) { return d.type; });
 
35838             label.append('span')
 
35839                 .attr('class', 'entity-name')
 
35840                 .text(function(d) { return d.name; });
 
35842             enter.style('opacity', 0)
 
35844                 .style('opacity', 1);
 
35852         function mouseover(d) {
 
35853             if (d.id === -1) return;
 
35855             context.surface().selectAll(iD.util.entityOrMemberSelector([d.id], context.graph()))
 
35856                 .classed('hover', true);
 
35859         function mouseout() {
 
35860             context.surface().selectAll('.hover')
 
35861                 .classed('hover', false);
 
35864         function click(d) {
 
35865             d3.event.preventDefault();
 
35867                 context.map().centerZoom([d.location[1], d.location[0]], 20);
 
35869             else if (d.entity) {
 
35870                 if (d.entity.type === 'node') {
 
35871                     context.map().center(d.entity.loc);
 
35872                 } else if (d.entity.type === 'way') {
 
35873                     var center = context.projection(context.map().center()),
 
35874                         edge = iD.geo.chooseEdge(context.childNodes(d.entity), center, context.projection);
 
35875                     context.map().center(edge.loc);
 
35877                 context.enter(iD.modes.Select(context, [d.entity.id]).suppressMenu(true));
 
35879                 context.zoomToEntity(d.id);
 
35883         function geocode() {
 
35884             var searchVal = encodeURIComponent(search.property('value'));
 
35885             d3.json('https://nominatim.openstreetmap.org/search/' + searchVal + '?limit=10&format=json', function(err, resp) {
 
35886                 geocodeResults = resp || [];
 
35892     return featureList;
 
35894 iD.ui.flash = function(selection) {
 
35895     var modal = iD.ui.modal(selection);
 
35897     modal.select('.modal').classed('modal-flash', true);
 
35899     modal.select('.content')
 
35900         .classed('modal-section', true)
 
35902         .attr('class', 'description');
 
35904     modal.on('click.flash', function() { modal.remove(); });
 
35906     setTimeout(function() {
 
35913 iD.ui.FullScreen = function(context) {
 
35914     var element = context.container().node(),
 
35915         keybinding = d3.keybinding('full-screen');
 
35918     function getFullScreenFn() {
 
35919         if (element.requestFullscreen) {
 
35920             return element.requestFullscreen;
 
35921         } else if (element.msRequestFullscreen) {
 
35922             return  element.msRequestFullscreen;
 
35923         } else if (element.mozRequestFullScreen) {
 
35924             return  element.mozRequestFullScreen;
 
35925         } else if (element.webkitRequestFullscreen) {
 
35926             return element.webkitRequestFullscreen;
 
35930     function getExitFullScreenFn() {
 
35931         if (document.exitFullscreen) {
 
35932             return document.exitFullscreen;
 
35933         } else if (document.msExitFullscreen) {
 
35934             return  document.msExitFullscreen;
 
35935         } else if (document.mozCancelFullScreen) {
 
35936             return  document.mozCancelFullScreen;
 
35937         } else if (document.webkitExitFullscreen) {
 
35938             return document.webkitExitFullscreen;
 
35942     function isFullScreen() {
 
35943         return document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement ||
 
35944             document.msFullscreenElement;
 
35947     function isSupported() {
 
35948         return !!getFullScreenFn();
 
35951     function fullScreen() {
 
35952         d3.event.preventDefault();
 
35953         if (!isFullScreen()) {
 
35954             // button.classed('active', true);
 
35955             getFullScreenFn().apply(element);
 
35957             // button.classed('active', false);
 
35958             getExitFullScreenFn().apply(document);
 
35962     return function() { // selection) {
 
35963         if (!isSupported())
 
35966         // var tooltip = bootstrap.tooltip()
 
35967         //     .placement('left');
 
35969         // button = selection.append('button')
 
35970         //     .attr('title', t('full_screen'))
 
35971         //     .attr('tabindex', -1)
 
35972         //     .on('click', fullScreen)
 
35975         // button.append('span')
 
35976         //     .attr('class', 'icon full-screen');
 
35979             .on('f11', fullScreen)
 
35980             .on(iD.ui.cmd('⌘⇧F'), fullScreen);
 
35982         d3.select(document)
 
35986 iD.ui.Geolocate = function(context) {
 
35987     var geoOptions = { enableHighAccuracy: false, timeout: 6000 /* 6sec */ },
 
35988         locating = iD.ui.Loading(context).message(t('geolocate.locating')).blocking(true),
 
35992         context.enter(iD.modes.Browse(context));
 
35993         context.container().call(locating);
 
35994         navigator.geolocation.getCurrentPosition(success, error, geoOptions);
 
35996         // This timeout ensures that we still call finish() even if
 
35997         // the user declines to share their location in Firefox
 
35998         timeoutId = setTimeout(finish, 10000 /* 10sec */ );
 
36001     function success(position) {
 
36002         var map = context.map(),
 
36003             extent = iD.geo.Extent([position.coords.longitude, position.coords.latitude])
 
36004                 .padByMeters(position.coords.accuracy);
 
36006         map.centerZoom(extent.center(), Math.min(20, map.extentZoom(extent)));
 
36014     function finish() {
 
36015         locating.close();  // unblock ui
 
36016         if (timeoutId) { clearTimeout(timeoutId); }
 
36017         timeoutId = undefined;
 
36020     return function(selection) {
 
36021         if (!navigator.geolocation) return;
 
36023         selection.append('button')
 
36024             .attr('tabindex', -1)
 
36025             .attr('title', t('geolocate.title'))
 
36026             .on('click', click)
 
36027             .call(iD.svg.Icon('#icon-geolocate', 'light'))
 
36028             .call(bootstrap.tooltip()
 
36029                 .placement('left'));
 
36032 iD.ui.Help = function(context) {
 
36037         'help.editing_saving',
 
36046     var docs = docKeys.map(function(key) {
 
36049             title: text.split('\n')[0].replace('#', '').trim(),
 
36050             html: marked(text.split('\n').slice(1).join('\n'))
 
36054     function help(selection) {
 
36060         function toggle() {
 
36061             if (d3.event) d3.event.preventDefault();
 
36062             tooltip.hide(button);
 
36063             setVisible(!button.classed('active'));
 
36066         function setVisible(show) {
 
36067             if (show !== shown) {
 
36068                 button.classed('active', show);
 
36072                     selection.on('mousedown.help-inside', function() {
 
36073                         return d3.event.stopPropagation();
 
36075                     pane.style('display', 'block')
 
36076                         .style('right', '-500px')
 
36079                         .style('right', '0px');
 
36081                     pane.style('right', '0px')
 
36084                         .style('right', '-500px')
 
36085                         .each('end', function() {
 
36086                             d3.select(this).style('display', 'none');
 
36088                     selection.on('mousedown.help-inside', null);
 
36093         function clickHelp(d, i) {
 
36094             pane.property('scrollTop', 0);
 
36095             doctitle.html(d.title);
 
36097             body.selectAll('a')
 
36098                 .attr('target', '_blank');
 
36099             menuItems.classed('selected', function(m) {
 
36100                 return m.title === d.title;
 
36106                 var prevLink = nav.append('a')
 
36107                     .attr('class', 'previous')
 
36108                     .on('click', function() {
 
36109                         clickHelp(docs[i - 1], i - 1);
 
36111                 prevLink.append('span').html('◄ ' + docs[i - 1].title);
 
36113             if (i < docs.length - 1) {
 
36114                 var nextLink = nav.append('a')
 
36115                     .attr('class', 'next')
 
36116                     .on('click', function() {
 
36117                         clickHelp(docs[i + 1], i + 1);
 
36119                 nextLink.append('span').html(docs[i + 1].title + ' ►');
 
36123         function clickWalkthrough() {
 
36124             d3.select(document.body).call(iD.ui.intro(context));
 
36129         var pane = selection.append('div')
 
36130                 .attr('class', 'help-wrap map-overlay fillL col5 content hide'),
 
36131             tooltip = bootstrap.tooltip()
 
36134                 .title(iD.ui.tooltipHtml(t('help.title'), key)),
 
36135             button = selection.append('button')
 
36136                 .attr('tabindex', -1)
 
36137                 .on('click', toggle)
 
36138                 .call(iD.svg.Icon('#icon-help', 'light'))
 
36143         var toc = pane.append('ul')
 
36144             .attr('class', 'toc');
 
36146         var menuItems = toc.selectAll('li')
 
36151             .html(function(d) { return d.title; })
 
36152             .on('click', clickHelp);
 
36155             .attr('class','walkthrough')
 
36157             .text(t('splash.walkthrough'))
 
36158             .on('click', clickWalkthrough);
 
36160         var content = pane.append('div')
 
36161             .attr('class', 'left-content');
 
36163         var doctitle = content.append('h2')
 
36164             .text(t('help.title'));
 
36166         var body = content.append('div')
 
36167             .attr('class', 'body');
 
36169         var nav = content.append('div')
 
36170             .attr('class', 'nav');
 
36172         clickHelp(docs[0], 0);
 
36174         var keybinding = d3.keybinding('help')
 
36179         d3.select(document)
 
36182         context.surface().on('mousedown.help-outside', hide);
 
36183         context.container().on('mousedown.help-outside', hide);
 
36188 iD.ui.Info = function(context) {
 
36189     var key = iD.ui.cmd('⌘I'),
 
36190         imperial = (iD.detect().locale.toLowerCase() === 'en-us'),
 
36193     function info(selection) {
 
36194         function radiansToMeters(r) {
 
36195             // using WGS84 authalic radius (6371007.1809 m)
 
36196             return r * 6371007.1809;
 
36199         function steradiansToSqmeters(r) {
 
36200             // http://gis.stackexchange.com/a/124857/40446
 
36201             return r / 12.56637 * 510065621724000;
 
36204         function toLineString(feature) {
 
36205             if (feature.type === 'LineString') return feature;
 
36207             var result = { type: 'LineString', coordinates: [] };
 
36208             if (feature.type === 'Polygon') {
 
36209                 result.coordinates = feature.coordinates[0];
 
36210             } else if (feature.type === 'MultiPolygon') {
 
36211                 result.coordinates = feature.coordinates[0][0];
 
36217         function displayLength(m) {
 
36218             var d = m * (imperial ? 3.28084 : 1),
 
36237             // drop unnecessary precision
 
36238             p = d > 1000 ? 0 : d > 100 ? 1 : 2;
 
36240             return String(d.toFixed(p)) + ' ' + unit;
 
36243         function displayArea(m2) {
 
36244             var d = m2 * (imperial ? 10.7639111056 : 1),
 
36245                 d1, d2, p1, p2, unit1, unit2;
 
36248                 if (d >= 6969600) {     // > 0.25mi² show mi²
 
36256                 if (d > 4356 && d < 43560000) {   // 0.1 - 1000 acres
 
36262                 if (d >= 250000) {    // > 0.25km² show km²
 
36270                 if (d > 1000 && d < 10000000) {   // 0.1 - 1000 hectares
 
36276             // drop unnecessary precision
 
36277             p1 = d1 > 1000 ? 0 : d1 > 100 ? 1 : 2;
 
36278             p2 = d2 > 1000 ? 0 : d2 > 100 ? 1 : 2;
 
36280             return String(d1.toFixed(p1)) + ' ' + unit1 +
 
36281                 (d2 ? ' (' + String(d2.toFixed(p2)) + ' ' + unit2 + ')' : '');
 
36285         function redraw() {
 
36286             if (hidden) return;
 
36288             var resolver = context.graph(),
 
36289                 selected = _.filter(context.selectedIDs(), function(e) { return context.hasEntity(e); }),
 
36290                 singular = selected.length === 1 ? selected[0] : null,
 
36291                 extent = iD.geo.Extent(),
 
36296                 .attr('class', 'infobox-heading fillD')
 
36297                 .text(singular || t('infobox.selected', { n: selected.length }));
 
36299             if (!selected.length) return;
 
36302             for (var i = 0; i < selected.length; i++) {
 
36303                 entity = context.entity(selected[i]);
 
36304                 extent._extend(entity.extent(resolver));
 
36306             center = extent.center();
 
36309             var list = wrap.append('ul');
 
36311             // multiple wrap, just display extent center..
 
36314                     .text(t('infobox.center') + ': ' + center[0].toFixed(5) + ', ' + center[1].toFixed(5));
 
36318             // single wrap, display details..
 
36319             if (!entity) return;
 
36320             var geometry = entity.geometry(resolver);
 
36322             if (geometry === 'line' || geometry === 'area') {
 
36323                 var closed = (entity.type === 'relation') || (entity.isClosed() && !entity.isDegenerate()),
 
36324                     feature = entity.asGeoJSON(resolver),
 
36325                     length = radiansToMeters(d3.geo.length(toLineString(feature))),
 
36326                     lengthLabel = t('infobox.' + (closed ? 'perimeter' : 'length')),
 
36327                     centroid = d3.geo.centroid(feature);
 
36330                     .text(t('infobox.geometry') + ': ' +
 
36331                         (closed ? t('infobox.closed') + ' ' : '') + t('geometry.' + geometry) );
 
36334                     var area = steradiansToSqmeters(entity.area(resolver));
 
36336                         .text(t('infobox.area') + ': ' + displayArea(area));
 
36340                     .text(lengthLabel + ': ' + displayLength(length));
 
36343                     .text(t('infobox.centroid') + ': ' + centroid[0].toFixed(5) + ', ' + centroid[1].toFixed(5));
 
36346                 var toggle  = imperial ? 'imperial' : 'metric';
 
36348                     .text(t('infobox.' + toggle))
 
36350                     .attr('class', 'button')
 
36351                     .on('click', function() {
 
36352                         d3.event.preventDefault();
 
36353                         imperial = !imperial;
 
36358                 var centerLabel = t('infobox.' + (entity.type === 'node' ? 'location' : 'center'));
 
36361                     .text(t('infobox.geometry') + ': ' + t('geometry.' + geometry));
 
36364                     .text(centerLabel + ': ' + center[0].toFixed(5) + ', ' + center[1].toFixed(5));
 
36369         function toggle() {
 
36370             if (d3.event) d3.event.preventDefault();
 
36376                     .style('display', 'block')
 
36377                     .style('opacity', 1)
 
36380                     .style('opacity', 0)
 
36381                     .each('end', function() {
 
36382                         d3.select(this).style('display', 'none');
 
36386                     .style('display', 'block')
 
36387                     .style('opacity', 0)
 
36390                     .style('opacity', 1);
 
36397         var wrap = selection.selectAll('.infobox')
 
36402             .attr('class', 'infobox fillD2')
 
36403             .style('display', (hidden ? 'none' : 'block'));
 
36406             .on('drawn.info', redraw);
 
36410         var keybinding = d3.keybinding('info')
 
36413         d3.select(document)
 
36419 iD.ui.Inspector = function(context) {
 
36420     var presetList = iD.ui.PresetList(context),
 
36421         entityEditor = iD.ui.EntityEditor(context),
 
36424         newFeature = false;
 
36426     function inspector(selection) {
 
36428             .entityID(entityID)
 
36429             .autofocus(newFeature)
 
36430             .on('choose', setPreset);
 
36434             .entityID(entityID)
 
36435             .on('choose', showList);
 
36437         var $wrap = selection.selectAll('.panewrap')
 
36440         var $enter = $wrap.enter().append('div')
 
36441             .attr('class', 'panewrap');
 
36443         $enter.append('div')
 
36444             .attr('class', 'preset-list-pane pane');
 
36446         $enter.append('div')
 
36447             .attr('class', 'entity-editor-pane pane');
 
36449         var $presetPane = $wrap.select('.preset-list-pane');
 
36450         var $editorPane = $wrap.select('.entity-editor-pane');
 
36452         var graph = context.graph(),
 
36453             entity = context.entity(entityID),
 
36454             showEditor = state === 'hover' ||
 
36455                 entity.isUsed(graph) ||
 
36456                 entity.isHighwayIntersection(graph);
 
36459             $wrap.style('right', '0%');
 
36460             $editorPane.call(entityEditor);
 
36462             $wrap.style('right', '-100%');
 
36463             $presetPane.call(presetList);
 
36466         var $footer = selection.selectAll('.footer')
 
36469         $footer.enter().append('div')
 
36470             .attr('class', 'footer');
 
36472         selection.select('.footer')
 
36473             .call(iD.ui.ViewOnOSM(context)
 
36474                 .entityID(entityID));
 
36476         function showList(preset) {
 
36478                 .styleTween('right', function() { return d3.interpolate('0%', '-100%'); });
 
36480             $presetPane.call(presetList
 
36485         function setPreset(preset) {
 
36487                 .styleTween('right', function() { return d3.interpolate('-100%', '0%'); });
 
36489             $editorPane.call(entityEditor
 
36494     inspector.state = function(_) {
 
36495         if (!arguments.length) return state;
 
36497         entityEditor.state(state);
 
36501     inspector.entityID = function(_) {
 
36502         if (!arguments.length) return entityID;
 
36507     inspector.newFeature = function(_) {
 
36508         if (!arguments.length) return newFeature;
 
36515 iD.ui.intro = function(context) {
 
36518     function intro(selection) {
 
36520         function localizedName(id) {
 
36522                 n2140018997: 'city_hall',
 
36523                 n367813436: 'fire_department',
 
36524                 w203988286: 'memory_isle_park',
 
36525                 w203972937: 'riverwalk_trail',
 
36526                 w203972938: 'riverwalk_trail',
 
36527                 w203972940: 'riverwalk_trail',
 
36528                 w41785752: 'w_michigan_ave',
 
36529                 w134150789: 'w_michigan_ave',
 
36530                 w134150795: 'w_michigan_ave',
 
36531                 w134150800: 'w_michigan_ave',
 
36532                 w134150811: 'w_michigan_ave',
 
36533                 w134150802: 'e_michigan_ave',
 
36534                 w134150836: 'e_michigan_ave',
 
36535                 w41074896: 'e_michigan_ave',
 
36536                 w17965834: 'spring_st',
 
36537                 w203986457: 'scidmore_park',
 
36538                 w203049587: 'petting_zoo',
 
36539                 w17967397: 'n_andrews_st',
 
36540                 w17967315: 's_andrews_st',
 
36541                 w17967326: 'n_constantine_st',
 
36542                 w17966400: 's_constantine_st',
 
36543                 w170848823: 'rocky_river',
 
36544                 w170848824: 'rocky_river',
 
36545                 w170848331: 'rocky_river',
 
36546                 w17967752: 'railroad_dr',
 
36547                 w17965998: 'conrail_rr',
 
36548                 w134150845: 'conrail_rr',
 
36549                 w170989131: 'st_joseph_river',
 
36550                 w143497377: 'n_main_st',
 
36551                 w134150801: 's_main_st',
 
36552                 w134150830: 's_main_st',
 
36553                 w17966462: 's_main_st',
 
36554                 w17967734: 'water_st',
 
36555                 w17964996: 'foster_st',
 
36556                 w170848330: 'portage_river',
 
36557                 w17965351: 'flower_st',
 
36558                 w17965502: 'elm_st',
 
36559                 w17965402: 'walnut_st',
 
36560                 w17964793: 'morris_ave',
 
36561                 w17967444: 'east_st',
 
36562                 w17966984: 'portage_ave'
 
36564             return features[id] && t('intro.graph.' + features[id]);
 
36567         context.enter(iD.modes.Browse(context));
 
36569         // Save current map state
 
36570         var history = context.history().toJSON(),
 
36571             hash = window.location.hash,
 
36572             center = context.map().center(),
 
36573             zoom = context.map().zoom(),
 
36574             background = context.background().baseLayerSource(),
 
36575             opacity = d3.selectAll('#map .layer-background').style('opacity'),
 
36576             loadedTiles = context.connection().loadedTiles(),
 
36577             baseEntities = context.history().graph().base().entities,
 
36581         context.inIntro(true);
 
36583         // Load semi-real data used in intro
 
36584         context.connection().toggle(false).flush();
 
36585         context.history().reset();
 
36587         introGraph = JSON.parse(iD.introGraph);
 
36588         for (var key in introGraph) {
 
36589             introGraph[key] = iD.Entity(introGraph[key]);
 
36590             name = localizedName(key);
 
36592                 introGraph[key].tags.name = name;
 
36595         context.history().merge(d3.values(iD.Graph().load(introGraph).entities));
 
36596         context.background().bing();
 
36598         d3.selectAll('#map .layer-background').style('opacity', 1);
 
36600         var curtain = d3.curtain();
 
36601         selection.call(curtain);
 
36603         function reveal(box, text, options) {
 
36604             options = options || {};
 
36605             if (text) curtain.reveal(box, text, options.tooltipClass, options.duration);
 
36606             else curtain.reveal(box, '', '', options.duration);
 
36609         var steps = ['navigation', 'point', 'area', 'line', 'startEditing'].map(function(step, i) {
 
36610             var s = iD.ui.intro[step](context, reveal)
 
36611                 .on('done', function() {
 
36612                     entered.filter(function(d) {
 
36613                         return d.title === s.title;
 
36614                     }).classed('finished', true);
 
36615                     enter(steps[i + 1]);
 
36620         steps[steps.length - 1].on('startEditing', function() {
 
36623             d3.selectAll('#map .layer-background').style('opacity', opacity);
 
36624             context.connection().toggle(true).flush().loadedTiles(loadedTiles);
 
36625             context.history().reset().merge(d3.values(baseEntities));
 
36626             context.background().baseLayerSource(background);
 
36627             if (history) context.history().fromJSON(history, false);
 
36628             context.map().centerZoom(center, zoom);
 
36629             window.location.replace(hash);
 
36630             context.inIntro(false);
 
36633         var navwrap = selection.append('div').attr('class', 'intro-nav-wrap fillD');
 
36635         var buttonwrap = navwrap.append('div')
 
36636             .attr('class', 'joined')
 
36637             .selectAll('button.step');
 
36639         var entered = buttonwrap
 
36643             .attr('class', 'step')
 
36644             .on('click', enter);
 
36647             .call(iD.svg.Icon('#icon-apply', 'pre-text'));
 
36651             .text(function(d) { return t(d.title); });
 
36655         function enter (newStep) {
 
36656             if (step) { step.exit(); }
 
36658             context.enter(iD.modes.Browse(context));
 
36663             entered.classed('active', function(d) {
 
36664                 return d.title === step.title;
 
36672 iD.ui.intro.pointBox = function(point, context) {
 
36673     var rect = context.surfaceRect();
 
36674     point = context.projection(point);
 
36676         left: point[0] + rect.left - 30,
 
36677         top: point[1] + rect.top - 50,
 
36683 iD.ui.intro.pad = function(box, padding, context) {
 
36684     if (box instanceof Array) {
 
36685         var rect = context.surfaceRect();
 
36686         box = context.projection(box);
 
36688             left: box[0] + rect.left,
 
36689             top: box[1] + rect.top
 
36693         left: box.left - padding,
 
36694         top: box.top - padding,
 
36695         width: (box.width || 0) + 2 * padding,
 
36696         height: (box.width || 0) + 2 * padding
 
36700 iD.ui.intro.icon = function(name, svgklass) {
 
36701     return '<svg class="icon ' + (svgklass || '') + '">' +
 
36702         '<use xlink:href="' + name + '"></use></svg>';
 
36704 iD.ui.Lasso = function(context) {
 
36705     var group, polygon;
 
36707     lasso.coordinates = [];
 
36709     function lasso(selection) {
 
36711         context.container().classed('lasso', true);
 
36713         group = selection.append('g')
 
36714             .attr('class', 'lasso hide');
 
36716         polygon = group.append('path')
 
36717             .attr('class', 'lasso-path');
 
36719         group.call(iD.ui.Toggle(true));
 
36725             polygon.data([lasso.coordinates])
 
36726                 .attr('d', function(d) { return 'M' + d.join(' L') + ' Z'; });
 
36730     lasso.extent = function () {
 
36731         return lasso.coordinates.reduce(function(extent, point) {
 
36732             return extent.extend(iD.geo.Extent(point));
 
36733         }, iD.geo.Extent());
 
36736     lasso.p = function(_) {
 
36737         if (!arguments.length) return lasso;
 
36738         lasso.coordinates.push(_);
 
36743     lasso.close = function() {
 
36745             group.call(iD.ui.Toggle(false, function() {
 
36746                 d3.select(this).remove();
 
36749         context.container().classed('lasso', false);
 
36754 iD.ui.Loading = function(context) {
 
36759     var loading = function(selection) {
 
36760         modal = iD.ui.modal(selection, blocking);
 
36762         var loadertext = modal.select('.content')
 
36763             .classed('loading-modal', true)
 
36765             .attr('class', 'modal-section fillL');
 
36767         loadertext.append('img')
 
36768             .attr('class', 'loader')
 
36769             .attr('src', context.imagePath('loader-white.gif'));
 
36771         loadertext.append('h3')
 
36774         modal.select('button.close')
 
36775             .attr('class', 'hide');
 
36780     loading.message = function(_) {
 
36781         if (!arguments.length) return message;
 
36786     loading.blocking = function(_) {
 
36787         if (!arguments.length) return blocking;
 
36792     loading.close = function() {
 
36798 iD.ui.MapData = function(context) {
 
36800         features = context.features().keys(),
 
36801         layers = context.layers(),
 
36802         fills = ['wireframe', 'partial', 'full'],
 
36803         fillDefault = context.storage('area-fill') || 'partial',
 
36804         fillSelected = fillDefault;
 
36807     function map_data(selection) {
 
36809         function showsFeature(d) {
 
36810             return context.features().enabled(d);
 
36813         function autoHiddenFeature(d) {
 
36814             return context.features().autoHidden(d);
 
36817         function clickFeature(d) {
 
36818             context.features().toggle(d);
 
36822         function showsFill(d) {
 
36823             return fillSelected === d;
 
36826         function setFill(d) {
 
36827             _.each(fills, function(opt) {
 
36828                 context.surface().classed('fill-' + opt, Boolean(opt === d));
 
36832             if (d !== 'wireframe') {
 
36834                 context.storage('area-fill', d);
 
36839         function showsLayer(which) {
 
36840             var layer = layers.layer(which);
 
36842                 return layer.enabled();
 
36847         function setLayer(which, enabled) {
 
36848             var layer = layers.layer(which);
 
36850                 layer.enabled(enabled);
 
36855         function toggleLayer(which) {
 
36856             setLayer(which, !showsLayer(which));
 
36859         function clickGpx() {
 
36860             toggleLayer('gpx');
 
36863         function clickMapillaryImages() {
 
36864             toggleLayer('mapillary-images');
 
36865             if (!showsLayer('mapillary-images')) {
 
36866                 setLayer('mapillary-signs', false);
 
36870         function clickMapillarySigns() {
 
36871             toggleLayer('mapillary-signs');
 
36875         function drawMapillaryItems(selection) {
 
36876             var mapillaryImages = layers.layer('mapillary-images'),
 
36877                 mapillarySigns = layers.layer('mapillary-signs'),
 
36878                 supportsMapillaryImages = mapillaryImages && mapillaryImages.supported(),
 
36879                 supportsMapillarySigns = mapillarySigns && mapillarySigns.supported(),
 
36880                 showsMapillaryImages = supportsMapillaryImages && mapillaryImages.enabled(),
 
36881                 showsMapillarySigns = supportsMapillarySigns && mapillarySigns.enabled();
 
36883             var mapillaryList = selection
 
36884                 .selectAll('.layer-list-mapillary')
 
36891                 .attr('class', 'layer-list layer-list-mapillary');
 
36893             var mapillaryImageLayerItem = mapillaryList
 
36894                 .selectAll('.list-item-mapillary-images')
 
36895                 .data(supportsMapillaryImages ? [0] : []);
 
36897             var enterImages = mapillaryImageLayerItem.enter()
 
36899                 .attr('class', 'list-item-mapillary-images');
 
36901             var labelImages = enterImages.append('label')
 
36902                 .call(bootstrap.tooltip()
 
36903                     .title(t('mapillary_images.tooltip'))
 
36904                     .placement('top'));
 
36906             labelImages.append('input')
 
36907                 .attr('type', 'checkbox')
 
36908                 .on('change', clickMapillaryImages);
 
36910             labelImages.append('span')
 
36911                 .text(t('mapillary_images.title'));
 
36914             var mapillarySignLayerItem = mapillaryList
 
36915                 .selectAll('.list-item-mapillary-signs')
 
36916                 .data(supportsMapillarySigns ? [0] : []);
 
36918             var enterSigns = mapillarySignLayerItem.enter()
 
36920                 .attr('class', 'list-item-mapillary-signs');
 
36922             var labelSigns = enterSigns.append('label')
 
36923                 .call(bootstrap.tooltip()
 
36924                     .title(t('mapillary_signs.tooltip'))
 
36925                     .placement('top'));
 
36927             labelSigns.append('input')
 
36928                 .attr('type', 'checkbox')
 
36929                 .on('change', clickMapillarySigns);
 
36931             labelSigns.append('span')
 
36932                 .text(t('mapillary_signs.title'));
 
36935             mapillaryImageLayerItem
 
36936                 .classed('active', showsMapillaryImages)
 
36937                 .selectAll('input')
 
36938                 .property('checked', showsMapillaryImages);
 
36940             mapillarySignLayerItem
 
36941                 .classed('active', showsMapillarySigns)
 
36942                 .selectAll('input')
 
36943                 .property('disabled', !showsMapillaryImages)
 
36944                 .property('checked', showsMapillarySigns);
 
36946             mapillarySignLayerItem
 
36947                 .selectAll('label')
 
36948                 .classed('deemphasize', !showsMapillaryImages);
 
36951             mapillaryImageLayerItem.exit()
 
36953             mapillarySignLayerItem.exit()
 
36958         function drawGpxItem(selection) {
 
36959             var gpx = layers.layer('gpx'),
 
36960                 hasGpx = gpx && gpx.hasGpx(),
 
36961                 showsGpx = hasGpx && gpx.enabled();
 
36963             var gpxLayerItem = selection
 
36964                 .selectAll('.layer-list-gpx')
 
36965                 .data(gpx ? [0] : []);
 
36968             var enter = gpxLayerItem.enter()
 
36970                 .attr('class', 'layer-list layer-list-gpx')
 
36972                 .classed('list-item-gpx', true);
 
36974             enter.append('button')
 
36975                 .attr('class', 'list-item-gpx-extent')
 
36976                 .call(bootstrap.tooltip()
 
36977                     .title(t('gpx.zoom'))
 
36978                     .placement('left'))
 
36979                 .on('click', function() {
 
36980                     d3.event.preventDefault();
 
36981                     d3.event.stopPropagation();
 
36984                 .call(iD.svg.Icon('#icon-search'));
 
36986             enter.append('button')
 
36987                 .attr('class', 'list-item-gpx-browse')
 
36988                 .call(bootstrap.tooltip()
 
36989                     .title(t('gpx.browse'))
 
36990                     .placement('left'))
 
36991                 .on('click', function() {
 
36992                     d3.select(document.createElement('input'))
 
36993                         .attr('type', 'file')
 
36994                         .on('change', function() {
 
36995                             gpx.files(d3.event.target.files);
 
36999                 .call(iD.svg.Icon('#icon-geolocate'));
 
37001             var labelGpx = enter.append('label')
 
37002                 .call(bootstrap.tooltip()
 
37003                     .title(t('gpx.drag_drop'))
 
37004                     .placement('top'));
 
37006             labelGpx.append('input')
 
37007                 .attr('type', 'checkbox')
 
37008                 .on('change', clickGpx);
 
37010             labelGpx.append('span')
 
37011                 .text(t('gpx.local_layer'));
 
37015                 .classed('active', showsGpx)
 
37016                 .selectAll('input')
 
37017                 .property('disabled', !hasGpx)
 
37018                 .property('checked', showsGpx);
 
37021                 .selectAll('label')
 
37022                 .classed('deemphasize', !hasGpx);
 
37025             gpxLayerItem.exit()
 
37030         function drawList(selection, data, type, name, change, active) {
 
37031             var items = selection.selectAll('li')
 
37035             var enter = items.enter()
 
37037                 .attr('class', 'layer')
 
37038                 .call(bootstrap.tooltip()
 
37040                     .title(function(d) {
 
37041                         var tip = t(name + '.' + d + '.tooltip'),
 
37042                             key = (d === 'wireframe' ? 'W' : null);
 
37044                         if (name === 'feature' && autoHiddenFeature(d)) {
 
37045                             tip += '<div>' + t('map_data.autohidden') + '</div>';
 
37047                         return iD.ui.tooltipHtml(tip, key);
 
37052             var label = enter.append('label');
 
37054             label.append('input')
 
37055                 .attr('type', type)
 
37056                 .attr('name', name)
 
37057                 .on('change', change);
 
37059             label.append('span')
 
37060                 .text(function(d) { return t(name + '.' + d + '.description'); });
 
37064                 .classed('active', active)
 
37065                 .selectAll('input')
 
37066                 .property('checked', active)
 
37067                 .property('indeterminate', function(d) {
 
37068                     return (name === 'feature' && autoHiddenFeature(d));
 
37077         function update() {
 
37078             dataLayerContainer.call(drawMapillaryItems);
 
37079             dataLayerContainer.call(drawGpxItem);
 
37081             fillList.call(drawList, fills, 'radio', 'area_fill', setFill, showsFill);
 
37083             featureList.call(drawList, features, 'checkbox', 'feature', clickFeature, showsFeature);
 
37086         function hidePanel() {
 
37090         function togglePanel() {
 
37091             if (d3.event) d3.event.preventDefault();
 
37092             tooltip.hide(button);
 
37093             setVisible(!button.classed('active'));
 
37096         function toggleWireframe() {
 
37098                 d3.event.preventDefault();
 
37099                 d3.event.stopPropagation();
 
37101             setFill((fillSelected === 'wireframe' ? fillDefault : 'wireframe'));
 
37102             context.map().pan([0,0]);  // trigger a redraw
 
37105         function setVisible(show) {
 
37106             if (show !== shown) {
 
37107                 button.classed('active', show);
 
37112                     selection.on('mousedown.map_data-inside', function() {
 
37113                         return d3.event.stopPropagation();
 
37115                     content.style('display', 'block')
 
37116                         .style('right', '-300px')
 
37119                         .style('right', '0px');
 
37121                     content.style('display', 'block')
 
37122                         .style('right', '0px')
 
37125                         .style('right', '-300px')
 
37126                         .each('end', function() {
 
37127                             d3.select(this).style('display', 'none');
 
37129                     selection.on('mousedown.map_data-inside', null);
 
37135         var content = selection.append('div')
 
37136                 .attr('class', 'fillL map-overlay col3 content hide'),
 
37137             tooltip = bootstrap.tooltip()
 
37140                 .title(iD.ui.tooltipHtml(t('map_data.description'), key)),
 
37141             button = selection.append('button')
 
37142                 .attr('tabindex', -1)
 
37143                 .on('click', togglePanel)
 
37144                 .call(iD.svg.Icon('#icon-data', 'light'))
 
37148         content.append('h4')
 
37149             .text(t('map_data.title'));
 
37153         content.append('a')
 
37154             .text(t('map_data.data_layers'))
 
37156             .classed('hide-toggle', true)
 
37157             .classed('expanded', true)
 
37158             .on('click', function() {
 
37159                 var exp = d3.select(this).classed('expanded');
 
37160                 dataLayerContainer.style('display', exp ? 'none' : 'block');
 
37161                 d3.select(this).classed('expanded', !exp);
 
37162                 d3.event.preventDefault();
 
37165         var dataLayerContainer = content.append('div')
 
37166             .attr('class', 'data-data-layers')
 
37167             .style('display', 'block');
 
37171         content.append('a')
 
37172             .text(t('map_data.fill_area'))
 
37174             .classed('hide-toggle', true)
 
37175             .classed('expanded', false)
 
37176             .on('click', function() {
 
37177                 var exp = d3.select(this).classed('expanded');
 
37178                 fillContainer.style('display', exp ? 'none' : 'block');
 
37179                 d3.select(this).classed('expanded', !exp);
 
37180                 d3.event.preventDefault();
 
37183         var fillContainer = content.append('div')
 
37184             .attr('class', 'data-area-fills')
 
37185             .style('display', 'none');
 
37187         var fillList = fillContainer.append('ul')
 
37188             .attr('class', 'layer-list layer-fill-list');
 
37192         content.append('a')
 
37193             .text(t('map_data.map_features'))
 
37195             .classed('hide-toggle', true)
 
37196             .classed('expanded', false)
 
37197             .on('click', function() {
 
37198                 var exp = d3.select(this).classed('expanded');
 
37199                 featureContainer.style('display', exp ? 'none' : 'block');
 
37200                 d3.select(this).classed('expanded', !exp);
 
37201                 d3.event.preventDefault();
 
37204         var featureContainer = content.append('div')
 
37205             .attr('class', 'data-feature-filters')
 
37206             .style('display', 'none');
 
37208         var featureList = featureContainer.append('ul')
 
37209             .attr('class', 'layer-list layer-feature-list');
 
37213             .on('change.map_data-update', update);
 
37215         setFill(fillDefault);
 
37217         var keybinding = d3.keybinding('features')
 
37218             .on(key, togglePanel)
 
37219             .on('W', toggleWireframe)
 
37220             .on('B', hidePanel)
 
37221             .on('H', hidePanel);
 
37223         d3.select(document)
 
37226         context.surface().on('mousedown.map_data-outside', hidePanel);
 
37227         context.container().on('mousedown.map_data-outside', hidePanel);
 
37232 iD.ui.MapInMap = function(context) {
 
37235     function map_in_map(selection) {
 
37236         var backgroundLayer = iD.TileLayer(context),
 
37237             overlayLayers = {},
 
37238             projection = iD.geo.RawMercator(),
 
37239             gpxLayer = iD.svg.Gpx(projection, context).showLabels(false),
 
37240             debugLayer = iD.svg.Debug(projection, context),
 
37241             zoom = d3.behavior.zoom()
 
37242                 .scaleExtent([ztok(0.5), ztok(24)])
 
37243                 .on('zoom', zoomPan),
 
37244             transformed = false,
 
37247             zDiff = 6,    // by default, minimap renders at (main zoom - 6)
 
37248             tStart, tLast, tCurr, kLast, kCurr, tiles, viewport, timeoutId;
 
37250         function ztok(z) { return 256 * Math.pow(2, z); }
 
37251         function ktoz(k) { return Math.log(k) / Math.LN2 - 8; }
 
37254         function startMouse() {
 
37255             context.surface().on('mouseup.map-in-map-outside', endMouse);
 
37256             context.container().on('mouseup.map-in-map-outside', endMouse);
 
37258             tStart = tLast = tCurr = projection.translate();
 
37263         function zoomPan() {
 
37264             var e = d3.event.sourceEvent,
 
37265                 t = d3.event.translate,
 
37266                 k = d3.event.scale,
 
37267                 zMain = ktoz(context.projection.scale() * 2 * Math.PI),
 
37270             // restrict minimap zoom to < (main zoom - 3)
 
37271             if (zMini > zMain - 3) {
 
37273                 zoom.scale(kCurr).translate(tCurr);  // restore last good values
 
37279             zDiff = zMain - zMini;
 
37281             var scale = kCurr / kLast,
 
37282                 tX = (tCurr[0] / scale - tLast[0]) * scale,
 
37283                 tY = (tCurr[1] / scale - tLast[1]) * scale;
 
37285             iD.util.setTransform(tiles, tX, tY, scale);
 
37286             iD.util.setTransform(viewport, 0, 0, scale);
 
37287             transformed = true;
 
37291             e.preventDefault();
 
37292             e.stopPropagation();
 
37296         function endMouse() {
 
37297             context.surface().on('mouseup.map-in-map-outside', null);
 
37298             context.container().on('mouseup.map-in-map-outside', null);
 
37300             updateProjection();
 
37303             if (tCurr[0] !== tStart[0] && tCurr[1] !== tStart[1]) {
 
37304                 var dMini = wrap.dimensions(),
 
37305                     cMini = [ dMini[0] / 2, dMini[1] / 2 ];
 
37307                 context.map().center(projection.invert(cMini));
 
37312         function updateProjection() {
 
37313             var loc = context.map().center(),
 
37314                 dMini = wrap.dimensions(),
 
37315                 cMini = [ dMini[0] / 2, dMini[1] / 2 ],
 
37316                 tMain = context.projection.translate(),
 
37317                 kMain = context.projection.scale(),
 
37318                 zMain = ktoz(kMain * 2 * Math.PI),
 
37319                 zMini = Math.max(zMain - zDiff, 0.5),
 
37320                 kMini = ztok(zMini);
 
37324                 .scale(kMini / (2 * Math.PI));
 
37326             var s = projection(loc),
 
37327                 mouse = panning ? [ tCurr[0] - tStart[0], tCurr[1] - tStart[1] ] : [0, 0],
 
37329                     cMini[0] - s[0] + tMain[0] + mouse[0],
 
37330                     cMini[1] - s[1] + tMain[1] + mouse[1]
 
37335                 .clipExtent([[0, 0], dMini]);
 
37342             tLast = tCurr = tMini;
 
37343             kLast = kCurr = kMini;
 
37346                 iD.util.setTransform(tiles, 0, 0);
 
37347                 iD.util.setTransform(viewport, 0, 0);
 
37348                 transformed = false;
 
37353         function redraw() {
 
37354             if (hidden) return;
 
37356             updateProjection();
 
37358             var dMini = wrap.dimensions(),
 
37359                 zMini = ktoz(projection.scale() * 2 * Math.PI);
 
37361             // setup tile container
 
37363                 .selectAll('.map-in-map-tiles')
 
37369                 .attr('class', 'map-in-map-tiles');
 
37371             // redraw background
 
37373                 .source(context.background().baseLayerSource())
 
37374                 .projection(projection)
 
37375                 .dimensions(dMini);
 
37377             var background = tiles
 
37378                 .selectAll('.map-in-map-background')
 
37383                 .attr('class', 'map-in-map-background');
 
37386                 .call(backgroundLayer);
 
37390             var overlaySources = context.background().overlayLayerSources();
 
37391             var activeOverlayLayers = [];
 
37392             for (var i = 0; i < overlaySources.length; i++) {
 
37393                 if (overlaySources[i].validZoom(zMini)) {
 
37394                     if (!overlayLayers[i]) overlayLayers[i] = iD.TileLayer(context);
 
37395                     activeOverlayLayers.push(overlayLayers[i]
 
37396                         .source(overlaySources[i])
 
37397                         .projection(projection)
 
37398                         .dimensions(dMini));
 
37402             var overlay = tiles
 
37403                 .selectAll('.map-in-map-overlay')
 
37408                 .attr('class', 'map-in-map-overlay');
 
37410             var overlays = overlay
 
37412                 .data(activeOverlayLayers, function(d) { return d.source().name(); });
 
37414             overlays.enter().append('div');
 
37415             overlays.each(function(layer) {
 
37416                 d3.select(this).call(layer);
 
37423             var dataLayers = tiles
 
37424                 .selectAll('.map-in-map-data')
 
37429                 .attr('class', 'map-in-map-data');
 
37439             // redraw viewport bounding box
 
37441                 var getPath = d3.geo.path().projection(projection),
 
37442                     bbox = { type: 'Polygon', coordinates: [context.map().extent().polygon()] };
 
37444                 viewport = wrap.selectAll('.map-in-map-viewport')
 
37449                     .attr('class', 'map-in-map-viewport');
 
37451                 var path = viewport.selectAll('.map-in-map-bbox')
 
37456                     .attr('class', 'map-in-map-bbox');
 
37459                     .attr('d', getPath)
 
37460                     .classed('thick', function(d) { return getPath.area(d) < 30; });
 
37465         function queueRedraw() {
 
37466             clearTimeout(timeoutId);
 
37467             timeoutId = setTimeout(function() { redraw(); }, 300);
 
37471         function toggle() {
 
37472             if (d3.event) d3.event.preventDefault();
 
37476             var label = d3.select('.minimap-toggle');
 
37477             label.classed('active', !hidden)
 
37478                 .select('input').property('checked', !hidden);
 
37482                     .style('display', 'block')
 
37483                     .style('opacity', 1)
 
37486                     .style('opacity', 0)
 
37487                     .each('end', function() {
 
37488                         d3.select(this).style('display', 'none');
 
37492                     .style('display', 'block')
 
37493                     .style('opacity', 0)
 
37496                     .style('opacity', 1);
 
37502         iD.ui.MapInMap.toggle = toggle;
 
37504         var wrap = selection.selectAll('.map-in-map')
 
37509             .attr('class', 'map-in-map')
 
37510             .style('display', (hidden ? 'none' : 'block'))
 
37511             .on('mousedown.map-in-map', startMouse)
 
37512             .on('mouseup.map-in-map', endMouse)
 
37514             .on('dblclick.zoom', null);
 
37517             .on('drawn.map-in-map', function(drawn) {
 
37518                 if (drawn.full === true) redraw();
 
37523         var keybinding = d3.keybinding('map-in-map')
 
37526         d3.select(document)
 
37532 iD.ui.modal = function(selection, blocking) {
 
37533     var keybinding = d3.keybinding('modal');
 
37534     var previous = selection.select('div.modal');
 
37535     var animate = previous.empty();
 
37537     previous.transition()
 
37539         .style('opacity', 0)
 
37542     var shaded = selection
 
37544         .attr('class', 'shaded')
 
37545         .style('opacity', 0);
 
37547     shaded.close = function() {
 
37551             .style('opacity',0)
 
37556             .style('top','0px');
 
37562     var modal = shaded.append('div')
 
37563         .attr('class', 'modal fillL col6');
 
37566         shaded.on('click.remove-modal', function() {
 
37567             if (d3.event.target === this) {
 
37572         modal.append('button')
 
37573             .attr('class', 'close')
 
37574             .on('click', shaded.close)
 
37575             .call(iD.svg.Icon('#icon-close'));
 
37578             .on('⌫', shaded.close)
 
37579             .on('⎋', shaded.close);
 
37581         d3.select(document).call(keybinding);
 
37584     modal.append('div')
 
37585         .attr('class', 'content');
 
37588         shaded.transition().style('opacity', 1);
 
37590         shaded.style('opacity', 1);
 
37595 iD.ui.Modes = function(context) {
 
37597         iD.modes.AddPoint(context),
 
37598         iD.modes.AddLine(context),
 
37599         iD.modes.AddArea(context)];
 
37601     function editable() {
 
37602         return context.editable() && context.mode().id !== 'save';
 
37605     return function(selection) {
 
37606         var buttons = selection.selectAll('button.add-button')
 
37609        buttons.enter().append('button')
 
37610            .attr('tabindex', -1)
 
37611            .attr('class', function(mode) { return mode.id + ' add-button col4'; })
 
37612            .on('click.mode-buttons', function(mode) {
 
37613                if (mode.id === context.mode().id) {
 
37614                    context.enter(iD.modes.Browse(context));
 
37616                    context.enter(mode);
 
37619            .call(bootstrap.tooltip()
 
37620                .placement('bottom')
 
37622                .title(function(mode) {
 
37623                    return iD.ui.tooltipHtml(mode.description, mode.key);
 
37627             .on('move.modes', _.debounce(update, 500));
 
37630             .on('enter.modes', update);
 
37632         buttons.each(function(d) {
 
37634                 .call(iD.svg.Icon('#icon-' + d.button, 'pre-text'));
 
37637         buttons.append('span')
 
37638             .attr('class', 'label')
 
37639             .text(function(mode) { return mode.title; });
 
37641         context.on('enter.editor', function(entered) {
 
37642             buttons.classed('active', function(mode) { return entered.button === mode.button; });
 
37643             context.container()
 
37644                 .classed('mode-' + entered.id, true);
 
37647         context.on('exit.editor', function(exited) {
 
37648             context.container()
 
37649                 .classed('mode-' + exited.id, false);
 
37652         var keybinding = d3.keybinding('mode-buttons');
 
37654         modes.forEach(function(m) {
 
37655             keybinding.on(m.key, function() { if (editable()) context.enter(m); });
 
37658         d3.select(document)
 
37661         function update() {
 
37662             buttons.property('disabled', !editable());
 
37666 iD.ui.Notice = function(context) {
 
37667     return function(selection) {
 
37668         var div = selection.append('div')
 
37669             .attr('class', 'notice');
 
37671         var button = div.append('button')
 
37672             .attr('class', 'zoom-to notice')
 
37673             .on('click', function() { context.map().zoom(context.minEditableZoom()); });
 
37676             .call(iD.svg.Icon('#icon-plus', 'pre-text'))
 
37678             .attr('class', 'label')
 
37679             .text(t('zoom_in_edit'));
 
37681         function disableTooHigh() {
 
37682             div.style('display', context.editable() ? 'none' : 'block');
 
37686             .on('move.notice', _.debounce(disableTooHigh, 500));
 
37691 iD.ui.PresetIcon = function() {
 
37692     var preset, geometry;
 
37694     function presetIcon(selection) {
 
37695         selection.each(render);
 
37698     function render() {
 
37699         var selection = d3.select(this),
 
37700             p = preset.apply(this, arguments),
 
37701             geom = geometry.apply(this, arguments),
 
37702             icon = p.icon || (geom === 'line' ? 'other-line' : 'marker-stroked'),
 
37703             maki = iD.data.featureIcons.hasOwnProperty(icon + '-24');
 
37705         if (icon === 'dentist') maki = true;  // workaround for dentist icon missing in `maki-sprite.json`
 
37707         function tag_classes(p) {
 
37709             for (var i in p.tags) {
 
37711                 if (p.tags[i] !== '*') {
 
37712                     s += ' tag-' + i + '-' + p.tags[i];
 
37718         var $fill = selection.selectAll('.preset-icon-fill')
 
37721         $fill.enter().append('div');
 
37723         $fill.attr('class', function() {
 
37724             return 'preset-icon-fill preset-icon-fill-' + geom + tag_classes(p);
 
37727         var $frame = selection.selectAll('.preset-icon-frame')
 
37732             .call(iD.svg.Icon('#preset-icon-frame'));
 
37734         $frame.attr('class', function() {
 
37735             return 'preset-icon-frame ' + (geom === 'area' ? '' : 'hide');
 
37739         var $icon = selection.selectAll('.preset-icon')
 
37744             .attr('class', 'preset-icon')
 
37745             .call(iD.svg.Icon(''));
 
37748             .attr('class', 'preset-icon preset-icon-' + (maki ? '32' : (geom === 'area' ? '44' : '60')));
 
37750         $icon.selectAll('svg')
 
37751             .attr('class', function() {
 
37752                 return 'icon ' + icon + tag_classes(p);
 
37755         $icon.selectAll('use')       // workaround: maki parking-24 broken?
 
37756             .attr('href', '#' + icon + (maki ? ( icon === 'parking' ? '-18' : '-24') : ''));
 
37759     presetIcon.preset = function(_) {
 
37760         if (!arguments.length) return preset;
 
37761         preset = d3.functor(_);
 
37765     presetIcon.geometry = function(_) {
 
37766         if (!arguments.length) return geometry;
 
37767         geometry = d3.functor(_);
 
37773 iD.ui.preset = function(context) {
 
37774     var event = d3.dispatch('change'),
 
37781     function UIField(field, entity, show) {
 
37782         field = _.clone(field);
 
37784         field.input = iD.ui.preset[field.type](field, context)
 
37785             .on('change', event.change);
 
37787         if (field.input.entity) field.input.entity(entity);
 
37789         field.keys = field.keys || [field.key];
 
37793         field.shown = function() {
 
37794             return field.id === 'name' || field.show || _.some(field.keys, function(key) { return !!tags[key]; });
 
37797         field.modified = function() {
 
37798             var original = context.graph().base().entities[entity.id];
 
37799             return _.some(field.keys, function(key) {
 
37800                 return original ? tags[key] !== original.tags[key] : tags[key];
 
37804         field.revert = function() {
 
37805             var original = context.graph().base().entities[entity.id],
 
37807             field.keys.forEach(function(key) {
 
37808                 t[key] = original ? original.tags[key] : undefined;
 
37813         field.present = function() {
 
37814             return _.some(field.keys, function(key) {
 
37819         field.remove = function() {
 
37821             field.keys.forEach(function(key) {
 
37822                 t[key] = undefined;
 
37830     function fieldKey(field) {
 
37834     function presets(selection) {
 
37835         selection.call(iD.ui.Disclosure()
 
37836             .title(t('inspector.all_fields'))
 
37837             .expanded(context.storage('preset_fields.expanded') !== 'false')
 
37838             .on('toggled', toggled)
 
37839             .content(content));
 
37841         function toggled(expanded) {
 
37842             context.storage('preset_fields.expanded', expanded);
 
37846     function content(selection) {
 
37848             var entity = context.entity(id),
 
37849                 geometry = context.geometry(id);
 
37851             fields = [UIField(context.presets().field('name'), entity)];
 
37853             preset.fields.forEach(function(field) {
 
37854                 if (field.matchGeometry(geometry)) {
 
37855                     fields.push(UIField(field, entity, true));
 
37859             if (entity.isHighwayIntersection(context.graph())) {
 
37860                 fields.push(UIField(context.presets().field('restrictions'), entity, true));
 
37863             context.presets().universal().forEach(function(field) {
 
37864                 if (preset.fields.indexOf(field) < 0) {
 
37865                     fields.push(UIField(field, entity));
 
37870         var shown = fields.filter(function(field) { return field.shown(); }),
 
37871             notShown = fields.filter(function(field) { return !field.shown(); });
 
37873         var $form = selection.selectAll('.preset-form')
 
37876         $form.enter().append('div')
 
37877             .attr('class', 'preset-form inspector-inner fillL3');
 
37879         var $fields = $form.selectAll('.form-field')
 
37880             .data(shown, fieldKey);
 
37884         var $enter = $fields.enter()
 
37886             .attr('class', function(field) {
 
37887                 return 'form-field form-field-' + field.id;
 
37890         var $label = $enter.append('label')
 
37891             .attr('class', 'form-label')
 
37892             .attr('for', function(field) { return 'preset-input-' + field.id; })
 
37893             .text(function(field) { return field.label(); });
 
37895         var wrap = $label.append('div')
 
37896             .attr('class', 'form-label-button-wrap');
 
37898         wrap.append('button')
 
37899             .attr('class', 'remove-icon')
 
37900             .attr('tabindex', -1)
 
37901             .call(iD.svg.Icon('#operation-delete'));
 
37903         wrap.append('button')
 
37904             .attr('class', 'modified-icon')
 
37905             .attr('tabindex', -1)
 
37906             .call(iD.svg.Icon('#icon-undo'));
 
37910         $fields.select('.form-label-button-wrap .remove-icon')
 
37911             .on('click', remove);
 
37913         $fields.select('.modified-icon')
 
37914             .on('click', revert);
 
37918             .classed('modified', function(field) {
 
37919                 return field.modified();
 
37921             .classed('present', function(field) {
 
37922                 return field.present();
 
37924             .each(function(field) {
 
37925                 var reference = iD.ui.TagReference(field.reference || {key: field.key}, context);
 
37927                 if (state === 'hover') {
 
37928                     reference.showing(false);
 
37933                     .selectAll('input')
 
37934                     .on('keydown', function() {
 
37935                         // if user presses enter, and combobox is not active, accept edits..
 
37936                         if (d3.event.keyCode === 13 && d3.select('.combobox').empty()) {
 
37937                             context.enter(iD.modes.Browse(context));
 
37940                     .call(reference.body)
 
37941                     .select('.form-label-button-wrap')
 
37942                     .call(reference.button);
 
37944                 field.input.tags(tags);
 
37950         notShown = notShown.map(function(field) {
 
37952                 title: field.label(),
 
37953                 value: field.label(),
 
37958         var $more = selection.selectAll('.more-fields')
 
37959             .data((notShown.length > 0) ? [0] : []);
 
37961         $more.enter().append('div')
 
37962             .attr('class', 'more-fields')
 
37964                 .text(t('inspector.add_fields'));
 
37966         var $input = $more.selectAll('.value')
 
37969         $input.enter().append('input')
 
37970             .attr('class', 'value')
 
37971             .attr('type', 'text');
 
37974             .attr('placeholder', function() {
 
37975                 var placeholder = [];
 
37976                 for (var field in notShown) {
 
37977                     placeholder.push(notShown[field].title);
 
37979                 return placeholder.slice(0,3).join(', ') + ((placeholder.length > 3) ? '…' : '');
 
37981             .call(d3.combobox().data(notShown)
 
37983                 .on('accept', show));
 
37991         function show(field) {
 
37992             field = field.field;
 
37994             content(selection);
 
37995             field.input.focus();
 
37998         function revert(field) {
 
37999             d3.event.stopPropagation();
 
38000             d3.event.preventDefault();
 
38001             event.change(field.revert());
 
38004         function remove(field) {
 
38005             d3.event.stopPropagation();
 
38006             d3.event.preventDefault();
 
38007             event.change(field.remove());
 
38011     presets.preset = function(_) {
 
38012         if (!arguments.length) return preset;
 
38013         if (preset && preset.id === _.id) return presets;
 
38019     presets.state = function(_) {
 
38020         if (!arguments.length) return state;
 
38025     presets.tags = function(_) {
 
38026         if (!arguments.length) return tags;
 
38028         // Don't reset fields here.
 
38032     presets.entityID = function(_) {
 
38033         if (!arguments.length) return id;
 
38034         if (id === _) return presets;
 
38040     return d3.rebind(presets, event, 'on');
 
38042 iD.ui.PresetList = function(context) {
 
38043     var dispatch = d3.dispatch('choose'),
 
38048     function presetList(selection) {
 
38049         var entity = context.entity(id),
 
38050             geometry = context.geometry(id);
 
38052         // Treat entities on addr:interpolation lines as points, not vertices (#3241)
 
38053         if (geometry === 'vertex' && entity.isOnAddressLine(context.graph())) {
 
38054             geometry = 'point';
 
38057         var presets = context.presets().matchGeometry(geometry);
 
38059         selection.html('');
 
38061         var messagewrap = selection.append('div')
 
38062             .attr('class', 'header fillL cf');
 
38064         var message = messagewrap.append('h3')
 
38065             .text(t('inspector.choose'));
 
38067         if (context.entity(id).isUsed(context.graph())) {
 
38068             messagewrap.append('button')
 
38069                 .attr('class', 'preset-choose')
 
38070                 .on('click', function() { dispatch.choose(currentPreset); })
 
38074             messagewrap.append('button')
 
38075                 .attr('class', 'close')
 
38076                 .on('click', function() {
 
38077                     context.enter(iD.modes.Browse(context));
 
38079                 .call(iD.svg.Icon('#icon-close'));
 
38082         function keydown() {
 
38083             // hack to let delete shortcut work when search is autofocused
 
38084             if (search.property('value').length === 0 &&
 
38085                 (d3.event.keyCode === d3.keybinding.keyCodes['⌫'] ||
 
38086                  d3.event.keyCode === d3.keybinding.keyCodes['⌦'])) {
 
38087                 d3.event.preventDefault();
 
38088                 d3.event.stopPropagation();
 
38089                 iD.operations.Delete([id], context)();
 
38090             } else if (search.property('value').length === 0 &&
 
38091                 (d3.event.ctrlKey || d3.event.metaKey) &&
 
38092                 d3.event.keyCode === d3.keybinding.keyCodes.z) {
 
38093                 d3.event.preventDefault();
 
38094                 d3.event.stopPropagation();
 
38096             } else if (!d3.event.ctrlKey && !d3.event.metaKey) {
 
38097                 d3.select(this).on('keydown', null);
 
38101         function keypress() {
 
38103             var value = search.property('value');
 
38104             if (d3.event.keyCode === 13 && value.length) {
 
38105                 list.selectAll('.preset-list-item:first-child').datum().choose();
 
38109         function inputevent() {
 
38110             var value = search.property('value');
 
38111             list.classed('filtered', value.length);
 
38112             if (value.length) {
 
38113                 var results = presets.search(value, geometry);
 
38114                 message.text(t('inspector.results', {
 
38115                     n: results.collection.length,
 
38118                 list.call(drawList, results);
 
38120                 list.call(drawList, context.presets().defaults(geometry, 36));
 
38121                 message.text(t('inspector.choose'));
 
38125         var searchWrap = selection.append('div')
 
38126             .attr('class', 'search-header');
 
38128         var search = searchWrap.append('input')
 
38129             .attr('class', 'preset-search-input')
 
38130             .attr('placeholder', t('inspector.search'))
 
38131             .attr('type', 'search')
 
38132             .on('keydown', keydown)
 
38133             .on('keypress', keypress)
 
38134             .on('input', inputevent);
 
38137             .call(iD.svg.Icon('#icon-search', 'pre-text'));
 
38140             search.node().focus();
 
38143         var listWrap = selection.append('div')
 
38144             .attr('class', 'inspector-body');
 
38146         var list = listWrap.append('div')
 
38147             .attr('class', 'preset-list fillL cf')
 
38148             .call(drawList, context.presets().defaults(geometry, 36));
 
38151     function drawList(list, presets) {
 
38152         var collection = presets.collection.map(function(preset) {
 
38153             return preset.members ? CategoryItem(preset) : PresetItem(preset);
 
38156         var items = list.selectAll('.preset-list-item')
 
38157             .data(collection, function(d) { return d.preset.id; });
 
38159         items.enter().append('div')
 
38160             .attr('class', function(item) { return 'preset-list-item preset-' + item.preset.id.replace('/', '-'); })
 
38161             .classed('current', function(item) { return item.preset === currentPreset; })
 
38162             .each(function(item) {
 
38163                 d3.select(this).call(item);
 
38165             .style('opacity', 0)
 
38167             .style('opacity', 1);
 
38175     function CategoryItem(preset) {
 
38176         var box, sublist, shown = false;
 
38178         function item(selection) {
 
38179             var wrap = selection.append('div')
 
38180                 .attr('class', 'preset-list-button-wrap category col12');
 
38182             wrap.append('button')
 
38183                 .attr('class', 'preset-list-button')
 
38184                 .classed('expanded', false)
 
38185                 .call(iD.ui.PresetIcon()
 
38186                     .geometry(context.geometry(id))
 
38188                 .on('click', function() {
 
38189                     var isExpanded = d3.select(this).classed('expanded');
 
38190                     var triangle = isExpanded ? '▶ ' :  '▼ ';
 
38191                     d3.select(this).classed('expanded', !isExpanded);
 
38192                     d3.select(this).selectAll('.label').text(triangle + preset.name());
 
38196                 .attr('class', 'label')
 
38198                   return '▶ ' + preset.name();
 
38201             box = selection.append('div')
 
38202                 .attr('class', 'subgrid col12')
 
38203                 .style('max-height', '0px')
 
38204                 .style('opacity', 0);
 
38207                 .attr('class', 'arrow');
 
38209             sublist = box.append('div')
 
38210                 .attr('class', 'preset-list fillL3 cf fl');
 
38213         item.choose = function() {
 
38214             if (!box || !sublist) return;
 
38220                     .style('opacity', '0')
 
38221                     .style('max-height', '0px')
 
38222                     .style('padding-bottom', '0px');
 
38225                 sublist.call(drawList, preset.members);
 
38228                     .style('opacity', '1')
 
38229                     .style('max-height', 200 + preset.members.collection.length * 80 + 'px')
 
38230                     .style('padding-bottom', '20px');
 
38234         item.preset = preset;
 
38239     function PresetItem(preset) {
 
38240         function item(selection) {
 
38241             var wrap = selection.append('div')
 
38242                 .attr('class', 'preset-list-button-wrap col12');
 
38244             wrap.append('button')
 
38245                 .attr('class', 'preset-list-button')
 
38246                 .call(iD.ui.PresetIcon()
 
38247                     .geometry(context.geometry(id))
 
38249                 .on('click', item.choose)
 
38251                 .attr('class', 'label')
 
38252                 .text(preset.name());
 
38254             wrap.call(item.reference.button);
 
38255             selection.call(item.reference.body);
 
38258         item.choose = function() {
 
38259             context.presets().choose(preset);
 
38262                 iD.actions.ChangePreset(id, currentPreset, preset),
 
38263                 t('operations.change_tags.annotation'));
 
38265             dispatch.choose(preset);
 
38268         item.help = function() {
 
38269             d3.event.stopPropagation();
 
38270             item.reference.toggle();
 
38273         item.preset = preset;
 
38274         item.reference = iD.ui.TagReference(preset.reference(context.geometry(id)), context);
 
38279     presetList.autofocus = function(_) {
 
38280         if (!arguments.length) return autofocus;
 
38285     presetList.entityID = function(_) {
 
38286         if (!arguments.length) return id;
 
38288         presetList.preset(context.presets().match(context.entity(id), context.graph()));
 
38292     presetList.preset = function(_) {
 
38293         if (!arguments.length) return currentPreset;
 
38298     return d3.rebind(presetList, dispatch, 'on');
 
38300 iD.ui.RadialMenu = function(context, operations) {
 
38305     var radialMenu = function(selection) {
 
38306         if (!operations.length)
 
38309         selection.node().parentNode.focus();
 
38311         function click(operation) {
 
38312             d3.event.stopPropagation();
 
38313             if (operation.disabled())
 
38316             radialMenu.close();
 
38319         menu = selection.append('g')
 
38320             .attr('class', 'radial-menu')
 
38321             .attr('transform', 'translate(' + center + ')')
 
38322             .attr('opacity', 0);
 
38325             .attr('opacity', 1);
 
38330             a1 = a0 + (operations.length - 1) * a;
 
38332         menu.append('path')
 
38333             .attr('class', 'radial-menu-background')
 
38334             .attr('d', 'M' + r * Math.sin(a0) + ',' +
 
38336                       ' A' + r + ',' + r + ' 0 ' + (operations.length > 5 ? '1' : '0') + ',0 ' +
 
38337                              (r * Math.sin(a1) + 1e-3) + ',' +
 
38338                              (r * Math.cos(a1) + 1e-3)) // Force positive-length path (#1305)
 
38339             .attr('stroke-width', 50)
 
38340             .attr('stroke-linecap', 'round');
 
38342         var button = menu.selectAll()
 
38346             .attr('class', function(d) { return 'radial-menu-item radial-menu-item-' + d.id; })
 
38347             .classed('disabled', function(d) { return d.disabled(); })
 
38348             .attr('transform', function(d, i) {
 
38349                 return 'translate(' + iD.geo.roundCoords([
 
38350                         r * Math.sin(a0 + i * a),
 
38351                         r * Math.cos(a0 + i * a)]).join(',') + ')';
 
38354         button.append('circle')
 
38356             .on('click', click)
 
38357             .on('mousedown', mousedown)
 
38358             .on('mouseover', mouseover)
 
38359             .on('mouseout', mouseout);
 
38361         button.append('use')
 
38362             .attr('transform', 'translate(-10,-10)')
 
38363             .attr('width', '20')
 
38364             .attr('height', '20')
 
38365             .attr('xlink:href', function(d) { return '#operation-' + d.id; });
 
38367         tooltip = d3.select(document.body)
 
38369             .attr('class', 'tooltip-inner radial-menu-tooltip');
 
38371         function mousedown() {
 
38372             d3.event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869
 
38375         function mouseover(d, i) {
 
38376             var rect = context.surfaceRect(),
 
38377                 angle = a0 + i * a,
 
38378                 top = rect.top + (r + 25) * Math.cos(angle) + center[1] + 'px',
 
38379                 left = rect.left + (r + 25) * Math.sin(angle) + center[0] + 'px',
 
38380                 bottom = rect.height - (r + 25) * Math.cos(angle) - center[1] + 'px',
 
38381                 right = rect.width - (r + 25) * Math.sin(angle) - center[0] + 'px';
 
38384                 .style('top', null)
 
38385                 .style('left', null)
 
38386                 .style('bottom', null)
 
38387                 .style('right', null)
 
38388                 .style('display', 'block')
 
38389                 .html(iD.ui.tooltipHtml(d.tooltip(), d.keys[0]));
 
38393                     .style('right', right)
 
38394                     .style('top', top);
 
38395             } else if (i >= 4) {
 
38397                     .style('left', left)
 
38398                     .style('bottom', bottom);
 
38401                     .style('left', left)
 
38402                     .style('top', top);
 
38406         function mouseout() {
 
38407             tooltip.style('display', 'none');
 
38411     radialMenu.close = function() {
 
38414                 .style('pointer-events', 'none')
 
38416                 .attr('opacity', 0)
 
38425     radialMenu.center = function(_) {
 
38426         if (!arguments.length) return center;
 
38433 iD.ui.RawMemberEditor = function(context) {
 
38436     function selectMember(d) {
 
38437         d3.event.preventDefault();
 
38438         context.enter(iD.modes.Select(context, [d.id]));
 
38441     function changeRole(d) {
 
38442         var role = d3.select(this).property('value');
 
38443         var member = {id: d.id, type: d.type, role: role};
 
38445             iD.actions.ChangeMember(d.relation.id, member, d.index),
 
38446             t('operations.change_role.annotation'));
 
38449     function deleteMember(d) {
 
38451             iD.actions.DeleteMember(d.relation.id, d.index),
 
38452             t('operations.delete_member.annotation'));
 
38454         if (!context.hasEntity(d.relation.id)) {
 
38455             context.enter(iD.modes.Browse(context));
 
38459     function rawMemberEditor(selection) {
 
38460         var entity = context.entity(id),
 
38463         entity.members.forEach(function(member, index) {
 
38470                 member: context.hasEntity(member.id)
 
38474         selection.call(iD.ui.Disclosure()
 
38475             .title(t('inspector.all_members') + ' (' + memberships.length + ')')
 
38477             .on('toggled', toggled)
 
38478             .content(content));
 
38480         function toggled(expanded) {
 
38482                 selection.node().parentNode.scrollTop += 200;
 
38486         function content($wrap) {
 
38487             var $list = $wrap.selectAll('.member-list')
 
38490             $list.enter().append('ul')
 
38491                 .attr('class', 'member-list');
 
38493             var $items = $list.selectAll('li')
 
38494                 .data(memberships, function(d) {
 
38495                     return iD.Entity.key(d.relation) + ',' + d.index + ',' +
 
38496                         (d.member ? iD.Entity.key(d.member) : 'incomplete');
 
38499             var $enter = $items.enter().append('li')
 
38500                 .attr('class', 'member-row form-field')
 
38501                 .classed('member-incomplete', function(d) { return !d.member; });
 
38503             $enter.each(function(d) {
 
38505                     var $label = d3.select(this).append('label')
 
38506                         .attr('class', 'form-label')
 
38509                         .on('click', selectMember);
 
38511                     $label.append('span')
 
38512                         .attr('class', 'member-entity-type')
 
38513                         .text(function(d) { return context.presets().match(d.member, context.graph()).name(); });
 
38515                     $label.append('span')
 
38516                         .attr('class', 'member-entity-name')
 
38517                         .text(function(d) { return iD.util.displayName(d.member); });
 
38520                     d3.select(this).append('label')
 
38521                         .attr('class', 'form-label')
 
38522                         .text(t('inspector.incomplete'));
 
38526             $enter.append('input')
 
38527                 .attr('class', 'member-role')
 
38528                 .property('type', 'text')
 
38529                 .attr('maxlength', 255)
 
38530                 .attr('placeholder', t('inspector.role'))
 
38531                 .property('value', function(d) { return d.role; })
 
38532                 .on('change', changeRole);
 
38534             $enter.append('button')
 
38535                 .attr('tabindex', -1)
 
38536                 .attr('class', 'remove button-input-action member-delete minor')
 
38537                 .on('click', deleteMember)
 
38538                 .call(iD.svg.Icon('#operation-delete'));
 
38545     rawMemberEditor.entityID = function(_) {
 
38546         if (!arguments.length) return id;
 
38548         return rawMemberEditor;
 
38551     return rawMemberEditor;
 
38553 iD.ui.RawMembershipEditor = function(context) {
 
38556     function selectRelation(d) {
 
38557         d3.event.preventDefault();
 
38558         context.enter(iD.modes.Select(context, [d.relation.id]));
 
38561     function changeRole(d) {
 
38562         var role = d3.select(this).property('value');
 
38564             iD.actions.ChangeMember(d.relation.id, _.extend({}, d.member, {role: role}), d.index),
 
38565             t('operations.change_role.annotation'));
 
38568     function addMembership(d, role) {
 
38573                 iD.actions.AddMember(d.relation.id, {id: id, type: context.entity(id).type, role: role}),
 
38574                 t('operations.add_member.annotation'));
 
38577             var relation = iD.Relation();
 
38580                 iD.actions.AddEntity(relation),
 
38581                 iD.actions.AddMember(relation.id, {id: id, type: context.entity(id).type, role: role}),
 
38582                 t('operations.add.annotation.relation'));
 
38584             context.enter(iD.modes.Select(context, [relation.id]));
 
38588     function deleteMembership(d) {
 
38590             iD.actions.DeleteMember(d.relation.id, d.index),
 
38591             t('operations.delete_member.annotation'));
 
38594     function relations(q) {
 
38595         var newRelation = {
 
38597                 value: t('inspector.new_relation')
 
38600             graph = context.graph();
 
38602         context.intersects(context.extent()).forEach(function(entity) {
 
38603             if (entity.type !== 'relation' || entity.id === id)
 
38606             var presetName = context.presets().match(entity, graph).name(),
 
38607                 entityName = iD.util.displayName(entity) || '';
 
38609             var value = presetName + ' ' + entityName;
 
38610             if (q && value.toLowerCase().indexOf(q.toLowerCase()) === -1)
 
38619         result.sort(function(a, b) {
 
38620             return iD.Relation.creationOrder(a.relation, b.relation);
 
38623         // Dedupe identical names by appending relation id - see #2891
 
38624         var dupeGroups = _(result)
 
38626             .filter(function(v) { return v.length > 1; })
 
38629         dupeGroups.forEach(function(group) {
 
38630             group.forEach(function(obj) {
 
38631                 obj.value += ' ' + obj.relation.id;
 
38635         result.unshift(newRelation);
 
38640     function rawMembershipEditor(selection) {
 
38641         var entity = context.entity(id),
 
38644         context.graph().parentRelations(entity).forEach(function(relation) {
 
38645             relation.members.forEach(function(member, index) {
 
38646                 if (member.id === entity.id) {
 
38647                     memberships.push({relation: relation, member: member, index: index});
 
38652         selection.call(iD.ui.Disclosure()
 
38653             .title(t('inspector.all_relations') + ' (' + memberships.length + ')')
 
38655             .on('toggled', toggled)
 
38656             .content(content));
 
38658         function toggled(expanded) {
 
38660                 selection.node().parentNode.scrollTop += 200;
 
38664         function content($wrap) {
 
38665             var $list = $wrap.selectAll('.member-list')
 
38668             $list.enter().append('ul')
 
38669                 .attr('class', 'member-list');
 
38671             var $items = $list.selectAll('li.member-row-normal')
 
38672                 .data(memberships, function(d) { return iD.Entity.key(d.relation) + ',' + d.index; });
 
38674             var $enter = $items.enter().append('li')
 
38675                 .attr('class', 'member-row member-row-normal form-field');
 
38677             var $label = $enter.append('label')
 
38678                 .attr('class', 'form-label')
 
38681                 .on('click', selectRelation);
 
38683             $label.append('span')
 
38684                 .attr('class', 'member-entity-type')
 
38685                 .text(function(d) { return context.presets().match(d.relation, context.graph()).name(); });
 
38687             $label.append('span')
 
38688                 .attr('class', 'member-entity-name')
 
38689                 .text(function(d) { return iD.util.displayName(d.relation); });
 
38691             $enter.append('input')
 
38692                 .attr('class', 'member-role')
 
38693                 .property('type', 'text')
 
38694                 .attr('maxlength', 255)
 
38695                 .attr('placeholder', t('inspector.role'))
 
38696                 .property('value', function(d) { return d.member.role; })
 
38697                 .on('change', changeRole);
 
38699             $enter.append('button')
 
38700                 .attr('tabindex', -1)
 
38701                 .attr('class', 'remove button-input-action member-delete minor')
 
38702                 .on('click', deleteMembership)
 
38703                 .call(iD.svg.Icon('#operation-delete'));
 
38709                 var $new = $list.selectAll('.member-row-new')
 
38712                 $enter = $new.enter().append('li')
 
38713                     .attr('class', 'member-row member-row-new form-field');
 
38715                 $enter.append('input')
 
38716                     .attr('type', 'text')
 
38717                     .attr('class', 'member-entity-input')
 
38718                     .call(d3.combobox()
 
38720                         .fetcher(function(value, callback) {
 
38721                             callback(relations(value));
 
38723                         .on('accept', function(d) {
 
38724                             addMembership(d, $new.select('.member-role').property('value'));
 
38727                 $enter.append('input')
 
38728                     .attr('class', 'member-role')
 
38729                     .property('type', 'text')
 
38730                     .attr('maxlength', 255)
 
38731                     .attr('placeholder', t('inspector.role'))
 
38732                     .on('change', changeRole);
 
38734                 $enter.append('button')
 
38735                     .attr('tabindex', -1)
 
38736                     .attr('class', 'remove button-input-action member-delete minor')
 
38737                     .on('click', deleteMembership)
 
38738                     .call(iD.svg.Icon('#operation-delete'));
 
38741                 $list.selectAll('.member-row-new')
 
38745             var $add = $wrap.selectAll('.add-relation')
 
38750                 .attr('class', 'add-relation')
 
38751                 .call(iD.svg.Icon('#icon-plus', 'light'));
 
38753             $wrap.selectAll('.add-relation')
 
38754                 .on('click', function() {
 
38757                     $list.selectAll('.member-entity-input').node().focus();
 
38762     rawMembershipEditor.entityID = function(_) {
 
38763         if (!arguments.length) return id;
 
38765         return rawMembershipEditor;
 
38768     return rawMembershipEditor;
 
38770 iD.ui.RawTagEditor = function(context) {
 
38771     var event = d3.dispatch('change'),
 
38778     function rawTagEditor(selection) {
 
38779         var count = Object.keys(tags).filter(function(d) { return d; }).length;
 
38781         selection.call(iD.ui.Disclosure()
 
38782             .title(t('inspector.all_tags') + ' (' + count + ')')
 
38783             .expanded(context.storage('raw_tag_editor.expanded') === 'true' || preset.isFallback())
 
38784             .on('toggled', toggled)
 
38785             .content(content));
 
38787         function toggled(expanded) {
 
38788             context.storage('raw_tag_editor.expanded', expanded);
 
38790                 selection.node().parentNode.scrollTop += 200;
 
38795     function content($wrap) {
 
38796         var entries = d3.entries(tags);
 
38798         if (!entries.length || showBlank) {
 
38800             entries.push({key: '', value: ''});
 
38803         var $list = $wrap.selectAll('.tag-list')
 
38806         $list.enter().append('ul')
 
38807             .attr('class', 'tag-list');
 
38809         var $newTag = $wrap.selectAll('.add-tag')
 
38814             .attr('class', 'add-tag')
 
38815             .call(iD.svg.Icon('#icon-plus', 'light'));
 
38817         $newTag.on('click', addTag);
 
38819         var $items = $list.selectAll('li')
 
38820             .data(entries, function(d) { return d.key; });
 
38824         var $enter = $items.enter().append('li')
 
38825             .attr('class', 'tag-row cf');
 
38827         $enter.append('div')
 
38828             .attr('class', 'key-wrap')
 
38830             .property('type', 'text')
 
38831             .attr('class', 'key')
 
38832             .attr('maxlength', 255);
 
38834         $enter.append('div')
 
38835             .attr('class', 'input-wrap-position')
 
38837             .property('type', 'text')
 
38838             .attr('class', 'value')
 
38839             .attr('maxlength', 255);
 
38841         $enter.append('button')
 
38842             .attr('tabindex', -1)
 
38843             .attr('class', 'remove minor')
 
38844             .call(iD.svg.Icon('#operation-delete'));
 
38846         if (context.taginfo()) {
 
38847             $enter.each(bindTypeahead);
 
38854         $items.each(function(tag) {
 
38855             var isRelation = (context.entity(id).type === 'relation'),
 
38857             if (isRelation && tag.key === 'type')
 
38858                 reference = iD.ui.TagReference({rtype: tag.value}, context);
 
38860                 reference = iD.ui.TagReference({key: tag.key, value: tag.value}, context);
 
38862             if (state === 'hover') {
 
38863                 reference.showing(false);
 
38867                 .call(reference.button)
 
38868                 .call(reference.body);
 
38871         $items.select('input.key')
 
38872             .attr('title', function(d) { return d.key; })
 
38873             .value(function(d) { return d.key; })
 
38874             .on('blur', keyChange)
 
38875             .on('change', keyChange);
 
38877         $items.select('input.value')
 
38878             .attr('title', function(d) { return d.value; })
 
38879             .value(function(d) { return d.value; })
 
38880             .on('blur', valueChange)
 
38881             .on('change', valueChange)
 
38882             .on('keydown.push-more', pushMore);
 
38884         $items.select('button.remove')
 
38885             .on('click', removeTag);
 
38891         function pushMore() {
 
38892             if (d3.event.keyCode === 9 && !d3.event.shiftKey &&
 
38893                 $list.selectAll('li:last-child input.value').node() === this) {
 
38898         function bindTypeahead() {
 
38899             var row = d3.select(this),
 
38900                 key = row.selectAll('input.key'),
 
38901                 value = row.selectAll('input.value');
 
38903             function sort(value, data) {
 
38904                 var sameletter = [],
 
38906                 for (var i = 0; i < data.length; i++) {
 
38907                     if (data[i].value.substring(0, value.length) === value) {
 
38908                         sameletter.push(data[i]);
 
38910                         other.push(data[i]);
 
38913                 return sameletter.concat(other);
 
38916             key.call(d3.combobox()
 
38917                 .fetcher(function(value, callback) {
 
38918                     context.taginfo().keys({
 
38920                         geometry: context.geometry(id),
 
38922                     }, function(err, data) {
 
38923                         if (!err) callback(sort(value, data));
 
38927             value.call(d3.combobox()
 
38928                 .fetcher(function(value, callback) {
 
38929                     context.taginfo().values({
 
38932                         geometry: context.geometry(id),
 
38934                     }, function(err, data) {
 
38935                         if (!err) callback(sort(value, data));
 
38940         function unbind() {
 
38941             var row = d3.select(this);
 
38943             row.selectAll('input.key')
 
38944                 .call(d3.combobox.off);
 
38946             row.selectAll('input.value')
 
38947                 .call(d3.combobox.off);
 
38950         function keyChange(d) {
 
38952                 kNew = this.value.trim(),
 
38955             if (kNew && kNew !== kOld) {
 
38956                 var match = kNew.match(/^(.*?)(?:_(\d+))?$/),
 
38958                     suffix = +(match[2] || 1);
 
38959                 while (tags[kNew]) {  // rename key if already in use
 
38960                     kNew = base + '_' + suffix++;
 
38963             tag[kOld] = undefined;
 
38964             tag[kNew] = d.value;
 
38965             d.key = kNew; // Maintain DOM identity through the subsequent update.
 
38970         function valueChange(d) {
 
38972             tag[d.key] = this.value;
 
38976         function removeTag(d) {
 
38978             tag[d.key] = undefined;
 
38980             d3.select(this.parentNode).remove();
 
38983         function addTag() {
 
38984             // Wrapped in a setTimeout in case it's being called from a blur
 
38985             // handler. Without the setTimeout, the call to `content` would
 
38986             // wipe out the pending value change.
 
38987             setTimeout(function() {
 
38990                 $list.selectAll('li:last-child input.key').node().focus();
 
38995     rawTagEditor.state = function(_) {
 
38996         if (!arguments.length) return state;
 
38998         return rawTagEditor;
 
39001     rawTagEditor.preset = function(_) {
 
39002         if (!arguments.length) return preset;
 
39004         return rawTagEditor;
 
39007     rawTagEditor.tags = function(_) {
 
39008         if (!arguments.length) return tags;
 
39010         return rawTagEditor;
 
39013     rawTagEditor.entityID = function(_) {
 
39014         if (!arguments.length) return id;
 
39016         return rawTagEditor;
 
39019     return d3.rebind(rawTagEditor, event, 'on');
 
39021 iD.ui.Restore = function(context) {
 
39022     return function(selection) {
 
39023         if (!context.history().lock() || !context.history().restorableChanges())
 
39026         var modal = iD.ui.modal(selection, true);
 
39028         modal.select('.modal')
 
39029             .attr('class', 'modal fillL col6');
 
39031         var introModal = modal.select('.content');
 
39033         introModal.attr('class','cf');
 
39035         introModal.append('div')
 
39036             .attr('class', 'modal-section')
 
39038             .text(t('restore.heading'));
 
39040         introModal.append('div')
 
39041             .attr('class','modal-section')
 
39043             .text(t('restore.description'));
 
39045         var buttonWrap = introModal.append('div')
 
39046             .attr('class', 'modal-actions cf');
 
39048         var restore = buttonWrap.append('button')
 
39049             .attr('class', 'restore col6')
 
39050             .text(t('restore.restore'))
 
39051             .on('click', function() {
 
39052                 context.history().restore();
 
39056         buttonWrap.append('button')
 
39057             .attr('class', 'reset col6')
 
39058             .text(t('restore.reset'))
 
39059             .on('click', function() {
 
39060                 context.history().clearSaved();
 
39064         restore.node().focus();
 
39067 iD.ui.Save = function(context) {
 
39068     var history = context.history(),
 
39069         key = iD.ui.cmd('⌘S');
 
39072     function saving() {
 
39073         return context.mode().id === 'save';
 
39077         d3.event.preventDefault();
 
39078         if (!context.inIntro() && !saving() && history.hasChanges()) {
 
39079             context.enter(iD.modes.Save(context));
 
39083     function getBackground(numChanges) {
 
39085         if (numChanges === 0) {
 
39087         } else if (numChanges <= 50) {
 
39088             step = numChanges / 50;
 
39089             return d3.interpolateRgb('#fff', '#ff8')(step);  // white -> yellow
 
39091             step = Math.min((numChanges - 50) / 50, 1.0);
 
39092             return d3.interpolateRgb('#ff8', '#f88')(step);  // yellow -> red
 
39096     return function(selection) {
 
39097         var tooltip = bootstrap.tooltip()
 
39098             .placement('bottom')
 
39100             .title(iD.ui.tooltipHtml(t('save.no_changes'), key));
 
39102         var button = selection.append('button')
 
39103             .attr('class', 'save col12 disabled')
 
39104             .attr('tabindex', -1)
 
39108         button.append('span')
 
39109             .attr('class', 'label')
 
39110             .text(t('save.title'));
 
39112         button.append('span')
 
39113             .attr('class', 'count')
 
39116         var keybinding = d3.keybinding('undo-redo')
 
39117             .on(key, save, true);
 
39119         d3.select(document)
 
39122         var numChanges = 0;
 
39124         context.history().on('change.save', function() {
 
39125             var _ = history.difference().summary().length;
 
39126             if (_ === numChanges)
 
39130             tooltip.title(iD.ui.tooltipHtml(t(numChanges > 0 ?
 
39131                     'save.help' : 'save.no_changes'), key));
 
39133             var background = getBackground(numChanges);
 
39136                 .classed('disabled', numChanges === 0)
 
39137                 .classed('has-count', numChanges > 0)
 
39138                 .style('background', background);
 
39140             button.select('span.count')
 
39142                 .style('background', background)
 
39143                 .style('border-color', background);
 
39146         context.on('enter.save', function() {
 
39147             button.property('disabled', saving());
 
39148             if (saving()) button.call(tooltip.hide);
 
39152 iD.ui.Scale = function(context) {
 
39153     var projection = context.projection,
 
39154         imperial = (iD.detect().locale.toLowerCase() === 'en-us'),
 
39158     function scaleDefs(loc1, loc2) {
 
39159         var lat = (loc2[1] + loc1[1]) / 2,
 
39160             conversion = (imperial ? 3.28084 : 1),
 
39161             dist = iD.geo.lonToMeters(loc2[0] - loc1[0], lat) * conversion,
 
39162             scale = { dist: 0, px: 0, text: '' },
 
39163             buckets, i, val, dLon;
 
39166             buckets = [5280000, 528000, 52800, 5280, 500, 50, 5, 1];
 
39168             buckets = [5000000, 500000, 50000, 5000, 500, 50, 5, 1];
 
39171         // determine a user-friendly endpoint for the scale
 
39172         for (i = 0; i < buckets.length; i++) {
 
39175                 scale.dist = Math.floor(dist / val) * val;
 
39180         dLon = iD.geo.metersToLon(scale.dist / conversion, lat);
 
39181         scale.px = Math.round(projection([loc1[0] + dLon, loc1[1]])[0]);
 
39184             if (scale.dist >= 5280) {
 
39185                 scale.dist /= 5280;
 
39186                 scale.text = String(scale.dist) + ' mi';
 
39188                 scale.text = String(scale.dist) + ' ft';
 
39191             if (scale.dist >= 1000) {
 
39192                 scale.dist /= 1000;
 
39193                 scale.text = String(scale.dist) + ' km';
 
39195                 scale.text = String(scale.dist) + ' m';
 
39202     function update(selection) {
 
39203         // choose loc1, loc2 along bottom of viewport (near where the scale will be drawn)
 
39204         var dims = context.map().dimensions(),
 
39205             loc1 = projection.invert([0, dims[1]]),
 
39206             loc2 = projection.invert([maxLength, dims[1]]),
 
39207             scale = scaleDefs(loc1, loc2);
 
39209         selection.select('#scalepath')
 
39210             .attr('d', 'M0.5,0.5v' + tickHeight + 'h' + scale.px + 'v-' + tickHeight);
 
39212         selection.select('#scaletext')
 
39213             .attr('x', scale.px + 8)
 
39214             .attr('y', tickHeight)
 
39219     return function(selection) {
 
39220         function switchUnits() {
 
39221             imperial = !imperial;
 
39222             selection.call(update);
 
39225         var g = selection.append('svg')
 
39226             .attr('id', 'scale')
 
39227             .on('click', switchUnits)
 
39229             .attr('transform', 'translate(10,11)');
 
39231         g.append('path').attr('id', 'scalepath');
 
39232         g.append('text').attr('id', 'scaletext');
 
39234         selection.call(update);
 
39236         context.map().on('move.scale', function() {
 
39241 iD.ui.SelectionList = function(context, selectedIDs) {
 
39243     function selectEntity(entity) {
 
39244         context.enter(iD.modes.Select(context, [entity.id]).suppressMenu(true));
 
39248     function selectionList(selection) {
 
39249         selection.classed('selection-list-pane', true);
 
39251         var header = selection.append('div')
 
39252             .attr('class', 'header fillL cf');
 
39254         header.append('h3')
 
39255             .text(t('inspector.multiselect'));
 
39257         var listWrap = selection.append('div')
 
39258             .attr('class', 'inspector-body');
 
39260         var list = listWrap.append('div')
 
39261             .attr('class', 'feature-list cf');
 
39263         context.history().on('change.selection-list', drawList);
 
39266         function drawList() {
 
39267             var entities = selectedIDs
 
39268                 .map(function(id) { return context.hasEntity(id); })
 
39269                 .filter(function(entity) { return entity; });
 
39271             var items = list.selectAll('.feature-list-item')
 
39272                 .data(entities, iD.Entity.key);
 
39274             var enter = items.enter().append('button')
 
39275                 .attr('class', 'feature-list-item')
 
39276                 .on('click', selectEntity);
 
39279             var label = enter.append('div')
 
39280                 .attr('class', 'label')
 
39281                 .call(iD.svg.Icon('', 'pre-text'));
 
39283             label.append('span')
 
39284                 .attr('class', 'entity-type');
 
39286             label.append('span')
 
39287                 .attr('class', 'entity-name');
 
39290             items.selectAll('use')
 
39291                 .attr('href', function() {
 
39292                     var entity = this.parentNode.parentNode.__data__;
 
39293                     return '#icon-' + context.geometry(entity.id);
 
39296             items.selectAll('.entity-type')
 
39297                 .text(function(entity) { return context.presets().match(entity, context.graph()).name(); });
 
39299             items.selectAll('.entity-name')
 
39300                 .text(function(entity) { return iD.util.displayName(entity); });
 
39308     return selectionList;
 
39311 iD.ui.Sidebar = function(context) {
 
39312     var inspector = iD.ui.Inspector(context),
 
39315     function sidebar(selection) {
 
39316         var featureListWrap = selection.append('div')
 
39317             .attr('class', 'feature-list-pane')
 
39318             .call(iD.ui.FeatureList(context));
 
39320         selection.call(iD.ui.Notice(context));
 
39322         var inspectorWrap = selection.append('div')
 
39323             .attr('class', 'inspector-hidden inspector-wrap fr');
 
39325         function hover(id) {
 
39326             if (!current && context.hasEntity(id)) {
 
39327                 featureListWrap.classed('inspector-hidden', true);
 
39328                 inspectorWrap.classed('inspector-hidden', false)
 
39329                     .classed('inspector-hover', true);
 
39331                 if (inspector.entityID() !== id || inspector.state() !== 'hover') {
 
39336                     inspectorWrap.call(inspector);
 
39338             } else if (!current) {
 
39339                 featureListWrap.classed('inspector-hidden', false);
 
39340                 inspectorWrap.classed('inspector-hidden', true);
 
39341                 inspector.state('hide');
 
39345         sidebar.hover = _.throttle(hover, 200);
 
39347         sidebar.select = function(id, newFeature) {
 
39348             if (!current && id) {
 
39349                 featureListWrap.classed('inspector-hidden', true);
 
39350                 inspectorWrap.classed('inspector-hidden', false)
 
39351                     .classed('inspector-hover', false);
 
39353                 if (inspector.entityID() !== id || inspector.state() !== 'select') {
 
39357                         .newFeature(newFeature);
 
39359                     inspectorWrap.call(inspector);
 
39361             } else if (!current) {
 
39362                 featureListWrap.classed('inspector-hidden', false);
 
39363                 inspectorWrap.classed('inspector-hidden', true);
 
39364                 inspector.state('hide');
 
39368         sidebar.show = function(component) {
 
39369             featureListWrap.classed('inspector-hidden', true);
 
39370             inspectorWrap.classed('inspector-hidden', true);
 
39371             if (current) current.remove();
 
39372             current = selection.append('div')
 
39373                 .attr('class', 'sidebar-component')
 
39377         sidebar.hide = function() {
 
39378             featureListWrap.classed('inspector-hidden', false);
 
39379             inspectorWrap.classed('inspector-hidden', true);
 
39380             if (current) current.remove();
 
39385     sidebar.hover = function() {};
 
39386     sidebar.hover.cancel = function() {};
 
39387     sidebar.select = function() {};
 
39388     sidebar.show = function() {};
 
39389     sidebar.hide = function() {};
 
39393 iD.ui.SourceSwitch = function(context) {
 
39397         d3.event.preventDefault();
 
39399         if (context.history().hasChanges() &&
 
39400             !window.confirm(t('source_switch.lose_changes'))) return;
 
39402         var live = d3.select(this)
 
39405         context.connection()
 
39406             .switch(live ? keys[1] : keys[0]);
 
39408         context.enter(iD.modes.Browse(context));
 
39412             .text(live ? t('source_switch.dev') : t('source_switch.live'))
 
39413             .classed('live', !live);
 
39416     var sourceSwitch = function(selection) {
 
39417         selection.append('a')
 
39419             .text(t('source_switch.live'))
 
39420             .classed('live', true)
 
39421             .attr('tabindex', -1)
 
39422             .on('click', click);
 
39425     sourceSwitch.keys = function(_) {
 
39426         if (!arguments.length) return keys;
 
39428         return sourceSwitch;
 
39431     return sourceSwitch;
 
39433 iD.ui.Spinner = function(context) {
 
39434     var connection = context.connection();
 
39436     return function(selection) {
 
39437         var img = selection.append('img')
 
39438             .attr('src', context.imagePath('loader-black.gif'))
 
39439             .style('opacity', 0);
 
39441         connection.on('loading.spinner', function() {
 
39443                 .style('opacity', 1);
 
39446         connection.on('loaded.spinner', function() {
 
39448                 .style('opacity', 0);
 
39452 iD.ui.Splash = function(context) {
 
39453     return function(selection) {
 
39454         if (context.storage('sawSplash'))
 
39457         context.storage('sawSplash', true);
 
39459         var modal = iD.ui.modal(selection);
 
39461         modal.select('.modal')
 
39462             .attr('class', 'modal-splash modal col6');
 
39464         var introModal = modal.select('.content')
 
39466             .attr('class', 'fillL');
 
39468         introModal.append('div')
 
39469             .attr('class','modal-section cf')
 
39470             .append('h3').text(t('splash.welcome'));
 
39472         introModal.append('div')
 
39473             .attr('class','modal-section')
 
39475             .html(t('splash.text', {
 
39476                 version: iD.version,
 
39477                 website: '<a href="http://ideditor.com/">ideditor.com</a>',
 
39478                 github: '<a href="https://github.com/openstreetmap/iD">github.com</a>'
 
39481         var buttons = introModal.append('div').attr('class', 'modal-actions cf');
 
39483         buttons.append('button')
 
39484             .attr('class', 'col6 walkthrough')
 
39485             .text(t('splash.walkthrough'))
 
39486             .on('click', function() {
 
39487                 d3.select(document.body).call(iD.ui.intro(context));
 
39491         buttons.append('button')
 
39492             .attr('class', 'col6 start')
 
39493             .text(t('splash.start'))
 
39494             .on('click', modal.close);
 
39496         modal.select('button.close').attr('class','hide');
 
39500 iD.ui.Status = function(context) {
 
39501     var connection = context.connection(),
 
39504     return function(selection) {
 
39506         function update() {
 
39508             connection.status(function(err, apiStatus) {
 
39510                 selection.html('');
 
39512                 if (err && errCount++ < 2) return;
 
39515                     selection.text(t('status.error'));
 
39517                 } else if (apiStatus === 'readonly') {
 
39518                     selection.text(t('status.readonly'));
 
39520                 } else if (apiStatus === 'offline') {
 
39521                     selection.text(t('status.offline'));
 
39524                 selection.attr('class', 'api-status ' + (err ? 'error' : apiStatus));
 
39525                 if (!err) errCount = 0;
 
39530         connection.on('auth', function() { update(selection); });
 
39531         window.setInterval(update, 90000);
 
39535 iD.ui.Success = function(context) {
 
39536     var dispatch = d3.dispatch('cancel'),
 
39539     function success(selection) {
 
39540         var message = (changeset.comment || t('success.edited_osm')).substring(0, 130) +
 
39541             ' ' + context.connection().changesetURL(changeset.id);
 
39543         var header = selection.append('div')
 
39544             .attr('class', 'header fillL');
 
39546         header.append('button')
 
39547             .attr('class', 'fr')
 
39548             .on('click', function() { dispatch.cancel(); })
 
39549             .call(iD.svg.Icon('#icon-close'));
 
39551         header.append('h3')
 
39552             .text(t('success.just_edited'));
 
39554         var body = selection.append('div')
 
39555             .attr('class', 'body save-success fillL');
 
39558             .html(t('success.help_html'));
 
39561             .attr('class', 'details')
 
39562             .attr('target', '_blank')
 
39563             .attr('tabindex', -1)
 
39564             .call(iD.svg.Icon('#icon-out-link', 'inline'))
 
39565             .attr('href', t('success.help_link_url'))
 
39567             .text(t('success.help_link_text'));
 
39569         var changesetURL = context.connection().changesetURL(changeset.id);
 
39572             .attr('class', 'button col12 osm')
 
39573             .attr('target', '_blank')
 
39574             .attr('href', changesetURL)
 
39575             .text(t('success.view_on_osm'));
 
39578             facebook: 'https://facebook.com/sharer/sharer.php?u=' + encodeURIComponent(changesetURL),
 
39579             twitter: 'https://twitter.com/intent/tweet?source=webclient&text=' + encodeURIComponent(message),
 
39580             google: 'https://plus.google.com/share?url=' + encodeURIComponent(changesetURL)
 
39583         body.selectAll('.button.social')
 
39584             .data(d3.entries(sharing))
 
39587             .attr('class', 'button social col4')
 
39588             .attr('target', '_blank')
 
39589             .attr('href', function(d) { return d.value; })
 
39590             .call(bootstrap.tooltip()
 
39591                 .title(function(d) { return t('success.' + d.key); })
 
39592                 .placement('bottom'))
 
39593             .each(function(d) { d3.select(this).call(iD.svg.Icon('#logo-' + d.key, 'social')); });
 
39596     success.changeset = function(_) {
 
39597         if (!arguments.length) return changeset;
 
39602     return d3.rebind(success, dispatch, 'on');
 
39604 iD.ui.TagReference = function(tag, context) {
 
39605     var tagReference = {},
 
39611     function findLocal(data) {
 
39612         var locale = iD.detect().locale.toLowerCase(),
 
39615         localized = _.find(data, function(d) {
 
39616             return d.lang.toLowerCase() === locale;
 
39618         if (localized) return localized;
 
39620         // try the non-regional version of a language, like
 
39621         // 'en' if the language is 'en-US'
 
39622         if (locale.indexOf('-') !== -1) {
 
39623             var first = locale.split('-')[0];
 
39624             localized = _.find(data, function(d) {
 
39625                 return d.lang.toLowerCase() === first;
 
39627             if (localized) return localized;
 
39630         // finally fall back to english
 
39631         return _.find(data, function(d) {
 
39632             return d.lang.toLowerCase() === 'en';
 
39636     function load(param) {
 
39637         button.classed('tag-reference-loading', true);
 
39639         context.taginfo().docs(param, function show(err, data) {
 
39641             if (!err && data) {
 
39642                 docs = findLocal(data);
 
39647             if (!docs || !docs.description) {
 
39648                 if (param.hasOwnProperty('value')) {
 
39649                     load(_.omit(param, 'value'));   // retry with key only
 
39651                     body.append('p').text(t('inspector.no_documentation_key'));
 
39657             if (docs.image && docs.image.thumb_url_prefix) {
 
39660                     .attr('class', 'wiki-image')
 
39661                     .attr('src', docs.image.thumb_url_prefix + '100' + docs.image.thumb_url_suffix)
 
39662                     .on('load', function() { done(); })
 
39663                     .on('error', function() { d3.select(this).remove(); done(); });
 
39670                 .text(docs.description);
 
39674                 .attr('target', '_blank')
 
39675                 .attr('tabindex', -1)
 
39676                 .attr('href', 'https://wiki.openstreetmap.org/wiki/' + docs.title)
 
39677                 .call(iD.svg.Icon('#icon-out-link', 'inline'))
 
39679                 .text(t('inspector.reference'));
 
39686         button.classed('tag-reference-loading', false);
 
39690             .style('max-height', '200px')
 
39691             .style('opacity', '1');
 
39696     function hide(selection) {
 
39697         selection = selection || body.transition().duration(200);
 
39700             .style('max-height', '0px')
 
39701             .style('opacity', '0');
 
39706     tagReference.button = function(selection) {
 
39707         button = selection.selectAll('.tag-reference-button')
 
39712             .attr('class', 'tag-reference-button')
 
39713             .attr('tabindex', -1)
 
39714             .call(iD.svg.Icon('#icon-inspect'));
 
39716         button.on('click', function () {
 
39717             d3.event.stopPropagation();
 
39718             d3.event.preventDefault();
 
39721             } else if (loaded) {
 
39724                 if (context.taginfo()) {
 
39731     tagReference.body = function(selection) {
 
39732         body = selection.selectAll('.tag-reference-body')
 
39735         body.enter().append('div')
 
39736             .attr('class', 'tag-reference-body cf')
 
39737             .style('max-height', '0')
 
39738             .style('opacity', '0');
 
39740         if (showing === false) {
 
39745     tagReference.showing = function(_) {
 
39746         if (!arguments.length) return showing;
 
39748         return tagReference;
 
39751     return tagReference;
 
39753 // toggles the visibility of ui elements, using a combination of the
 
39754 // hide class, which sets display=none, and a d3 transition for opacity.
 
39755 // this will cause blinking when called repeatedly, so check that the
 
39756 // value actually changes between calls.
 
39757 iD.ui.Toggle = function(show, callback) {
 
39758     return function(selection) {
 
39760             .style('opacity', show ? 0 : 1)
 
39761             .classed('hide', false)
 
39763             .style('opacity', show ? 1 : 0)
 
39764             .each('end', function() {
 
39766                     .classed('hide', !show)
 
39767                     .style('opacity', null);
 
39768                 if (callback) callback.apply(this);
 
39772 iD.ui.UndoRedo = function(context) {
 
39775         cmd: iD.ui.cmd('⌘Z'),
 
39776         action: function() { if (!(context.inIntro() || saving())) context.undo(); },
 
39777         annotation: function() { return context.history().undoAnnotation(); }
 
39780         cmd: iD.ui.cmd('⌘⇧Z'),
 
39781         action: function() {if (!(context.inIntro() || saving())) context.redo(); },
 
39782         annotation: function() { return context.history().redoAnnotation(); }
 
39785     function saving() {
 
39786         return context.mode().id === 'save';
 
39789     return function(selection) {
 
39790         var tooltip = bootstrap.tooltip()
 
39791             .placement('bottom')
 
39793             .title(function (d) {
 
39794                 return iD.ui.tooltipHtml(d.annotation() ?
 
39795                     t(d.id + '.tooltip', {action: d.annotation()}) :
 
39796                     t(d.id + '.nothing'), d.cmd);
 
39799         var buttons = selection.selectAll('button')
 
39801             .enter().append('button')
 
39802             .attr('class', 'col6 disabled')
 
39803             .on('click', function(d) { return d.action(); })
 
39806         buttons.each(function(d) {
 
39808                 .call(iD.svg.Icon('#icon-' + d.id));
 
39811         var keybinding = d3.keybinding('undo')
 
39812             .on(commands[0].cmd, function() { d3.event.preventDefault(); commands[0].action(); })
 
39813             .on(commands[1].cmd, function() { d3.event.preventDefault(); commands[1].action(); });
 
39815         d3.select(document)
 
39819             .on('change.undo_redo', update);
 
39822             .on('enter.undo_redo', update);
 
39824         function update() {
 
39826                 .property('disabled', saving())
 
39827                 .classed('disabled', function(d) { return !d.annotation(); })
 
39829                     var selection = d3.select(this);
 
39830                     if (selection.property('tooltipVisible')) {
 
39831                         selection.call(tooltip.show);
 
39837 iD.ui.ViewOnOSM = function(context) {
 
39840     function viewOnOSM(selection) {
 
39841         var entity = context.entity(id);
 
39843         selection.style('display', entity.isNew() ? 'none' : null);
 
39845         var $link = selection.selectAll('.view-on-osm')
 
39850             .attr('class', 'view-on-osm')
 
39851             .attr('target', '_blank')
 
39852             .call(iD.svg.Icon('#icon-out-link', 'inline'))
 
39854             .text(t('inspector.view_on_osm'));
 
39857             .attr('href', context.connection().entityURL(entity));
 
39860     viewOnOSM.entityID = function(_) {
 
39861         if (!arguments.length) return id;
 
39868 iD.ui.Zoom = function(context) {
 
39872         title: t('zoom.in'),
 
39873         action: context.zoomIn,
 
39878         title: t('zoom.out'),
 
39879         action: context.zoomOut,
 
39883     function zoomIn() {
 
39884         d3.event.preventDefault();
 
39885         if (!context.inIntro()) context.zoomIn();
 
39888     function zoomOut() {
 
39889         d3.event.preventDefault();
 
39890         if (!context.inIntro()) context.zoomOut();
 
39893     function zoomInFurther() {
 
39894         d3.event.preventDefault();
 
39895         if (!context.inIntro()) context.zoomInFurther();
 
39898     function zoomOutFurther() {
 
39899         d3.event.preventDefault();
 
39900         if (!context.inIntro()) context.zoomOutFurther();
 
39904     return function(selection) {
 
39905         var button = selection.selectAll('button')
 
39907             .enter().append('button')
 
39908             .attr('tabindex', -1)
 
39909             .attr('class', function(d) { return d.id; })
 
39910             .on('click.editor', function(d) { d.action(); })
 
39911             .call(bootstrap.tooltip()
 
39914                 .title(function(d) {
 
39915                     return iD.ui.tooltipHtml(d.title, d.key);
 
39918         button.each(function(d) {
 
39920                 .call(iD.svg.Icon('#icon-' + d.icon, 'light'));
 
39923         var keybinding = d3.keybinding('zoom');
 
39925         _.each(['=','ffequals','plus','ffplus'], function(key) {
 
39926             keybinding.on(key, zoomIn);
 
39927             keybinding.on('⇧' + key, zoomIn);
 
39928             keybinding.on(iD.ui.cmd('⌘' + key), zoomInFurther);
 
39929             keybinding.on(iD.ui.cmd('⌘⇧' + key), zoomInFurther);
 
39931         _.each(['-','ffminus','_','dash'], function(key) {
 
39932             keybinding.on(key, zoomOut);
 
39933             keybinding.on('⇧' + key, zoomOut);
 
39934             keybinding.on(iD.ui.cmd('⌘' + key), zoomOutFurther);
 
39935             keybinding.on(iD.ui.cmd('⌘⇧' + key), zoomOutFurther);
 
39938         d3.select(document)
 
39942 iD.ui.preset.access = function(field) {
 
39943     var dispatch = d3.dispatch('change'),
 
39946     function access(selection) {
 
39947         var wrap = selection.selectAll('.preset-input-wrap')
 
39950         wrap.enter().append('div')
 
39951             .attr('class', 'cf preset-input-wrap')
 
39954         items = wrap.select('ul').selectAll('li')
 
39959         var enter = items.enter().append('li')
 
39960             .attr('class', function(d) { return 'cf preset-access-' + d; });
 
39962         enter.append('span')
 
39963             .attr('class', 'col6 label preset-label-access')
 
39964             .attr('for', function(d) { return 'preset-input-access-' + d; })
 
39965             .text(function(d) { return field.t('types.' + d); });
 
39967         enter.append('div')
 
39968             .attr('class', 'col6 preset-input-access-wrap')
 
39970             .attr('type', 'text')
 
39971             .attr('class', 'preset-input-access')
 
39972             .attr('id', function(d) { return 'preset-input-access-' + d; })
 
39973             .each(function(d) {
 
39975                     .call(d3.combobox()
 
39976                         .data(access.options(d)));
 
39981         wrap.selectAll('.preset-input-access')
 
39982             .on('change', change)
 
39983             .on('blur', change);
 
39986     function change(d) {
 
39988         tag[d] = d3.select(this).value() || undefined;
 
39989         dispatch.change(tag);
 
39992     access.options = function(type) {
 
39993         var options = ['no', 'permissive', 'private', 'destination'];
 
39995         if (type !== 'access') {
 
39996             options.unshift('yes');
 
39997             options.push('designated');
 
39999             if (type === 'bicycle') {
 
40000                 options.push('dismount');
 
40004         return options.map(function(option) {
 
40006                 title: field.t('options.' + option + '.description'),
 
40012     var placeholders = {
 
40014             foot: 'designated',
 
40015             motor_vehicle: 'no'
 
40019             motor_vehicle: 'no',
 
40025             motor_vehicle: 'no'
 
40028             motor_vehicle: 'no',
 
40029             bicycle: 'designated'
 
40032             motor_vehicle: 'no',
 
40033             horse: 'designated'
 
40037             motor_vehicle: 'no',
 
40043             motor_vehicle: 'yes',
 
40048             motor_vehicle: 'yes'
 
40052             motor_vehicle: 'yes',
 
40058             motor_vehicle: 'yes',
 
40064             motor_vehicle: 'yes',
 
40070             motor_vehicle: 'yes',
 
40076             motor_vehicle: 'yes',
 
40082             motor_vehicle: 'yes',
 
40088             motor_vehicle: 'yes',
 
40093             motor_vehicle: 'yes'
 
40097             motor_vehicle: 'yes',
 
40103             motor_vehicle: 'yes',
 
40109             motor_vehicle: 'yes',
 
40115     access.tags = function(tags) {
 
40116         items.selectAll('.preset-input-access')
 
40117             .value(function(d) { return tags[d] || ''; })
 
40118             .attr('placeholder', function() {
 
40119                 return tags.access ? tags.access : field.placeholder();
 
40122         // items.selectAll('#preset-input-access-access')
 
40123         //     .attr('placeholder', 'yes');
 
40125         _.forEach(placeholders[tags.highway], function(v, k) {
 
40126             items.selectAll('#preset-input-access-' + k)
 
40127                 .attr('placeholder', function() { return (tags.access || v); });
 
40131     access.focus = function() {
 
40132         items.selectAll('.preset-input-access')
 
40136     return d3.rebind(access, dispatch, 'on');
 
40138 iD.ui.preset.address = function(field, context) {
 
40139     var dispatch = d3.dispatch('init', 'change'),
 
40152     function getStreets() {
 
40153         var extent = entity.extent(context.graph()),
 
40154             l = extent.center(),
 
40155             box = iD.geo.Extent(l).padByMeters(200);
 
40157         return context.intersects(box)
 
40158             .filter(isAddressable)
 
40160                 var loc = context.projection([
 
40161                     (extent[0][0] + extent[1][0]) / 2,
 
40162                     (extent[0][1] + extent[1][1]) / 2]),
 
40163                     choice = iD.geo.chooseEdge(context.childNodes(d), loc, context.projection);
 
40165                     title: d.tags.name,
 
40166                     value: d.tags.name,
 
40167                     dist: choice.distance
 
40169             }).sort(function(a, b) {
 
40170                 return a.dist - b.dist;
 
40173         function isAddressable(d) {
 
40174             return d.tags.highway && d.tags.name && d.type === 'way';
 
40178     function getCities() {
 
40179         var extent = entity.extent(context.graph()),
 
40180             l = extent.center(),
 
40181             box = iD.geo.Extent(l).padByMeters(200);
 
40183         return context.intersects(box)
 
40184             .filter(isAddressable)
 
40187                     title: d.tags['addr:city'] || d.tags.name,
 
40188                     value: d.tags['addr:city'] || d.tags.name,
 
40189                     dist: iD.geo.sphericalDistance(d.extent(context.graph()).center(), l)
 
40191             }).sort(function(a, b) {
 
40192                 return a.dist - b.dist;
 
40195         function isAddressable(d) {
 
40197                 (d.tags.admin_level === '8' || d.tags.border_type === 'city'))
 
40200             if (d.tags.place && d.tags.name && (
 
40201                     d.tags.place === 'city' ||
 
40202                     d.tags.place === 'town' ||
 
40203                     d.tags.place === 'village'))
 
40206             if (d.tags['addr:city']) return true;
 
40212     function getPostCodes() {
 
40213         var extent = entity.extent(context.graph()),
 
40214             l = extent.center(),
 
40215             box = iD.geo.Extent(l).padByMeters(200);
 
40217         return context.intersects(box)
 
40218             .filter(isAddressable)
 
40221                     title: d.tags['addr:postcode'],
 
40222                     value: d.tags['addr:postcode'],
 
40223                     dist: iD.geo.sphericalDistance(d.extent(context.graph()).center(), l)
 
40225             }).sort(function(a, b) {
 
40226                 return a.dist - b.dist;
 
40229         function isAddressable(d) {
 
40230             return d.tags['addr:postcode'];
 
40234     function address(selection) {
 
40235         isInitialized = false;
 
40237         wrap = selection.selectAll('.preset-input-wrap')
 
40244             .attr('class', 'preset-input-wrap');
 
40246         var center = entity.extent(context.graph()).center(),
 
40249         iD.services.nominatim().countryCode(center, function (err, countryCode) {
 
40250             addressFormat = _.find(iD.data.addressFormats, function (a) {
 
40251                 return a && a.countryCodes && _.includes(a.countryCodes, countryCode);
 
40252             }) || _.first(iD.data.addressFormats);
 
40255                 // Normalize widths.
 
40256                 var total = _.reduce(r, function(sum, field) {
 
40257                     return sum + (widths[field] || 0.5);
 
40260                 return r.map(function (field) {
 
40263                         width: (widths[field] || 0.5) / total
 
40268             wrap.selectAll('div')
 
40269                 .data(addressFormat.format)
 
40272                 .attr('class', 'addr-row')
 
40273                 .selectAll('input')
 
40277                 .property('type', 'text')
 
40278                 .attr('placeholder', function (d) { return field.t('placeholders.' + d.id); })
 
40279                 .attr('class', function (d) { return 'addr-' + d.id; })
 
40280                 .style('width', function (d) { return d.width * 100 + '%'; });
 
40284             wrap.selectAll('.addr-street')
 
40285                 .call(d3.combobox()
 
40286                     .fetcher(function(value, callback) {
 
40287                         callback(getStreets());
 
40290             wrap.selectAll('.addr-city')
 
40291                 .call(d3.combobox()
 
40292                     .fetcher(function(value, callback) {
 
40293                         callback(getCities());
 
40296             wrap.selectAll('.addr-postcode')
 
40297                 .call(d3.combobox()
 
40298                     .fetcher(function(value, callback) {
 
40299                         callback(getPostCodes());
 
40302             wrap.selectAll('input')
 
40303                 .on('blur', change())
 
40304                 .on('change', change());
 
40306             wrap.selectAll('input:not(.combobox-input)')
 
40307                 .on('input', change(true));
 
40310             isInitialized = true;
 
40314     function change(onInput) {
 
40315         return function() {
 
40318             wrap.selectAll('input')
 
40319                 .each(function (field) {
 
40320                     tags['addr:' + field.id] = this.value || undefined;
 
40323             dispatch.change(tags, onInput);
 
40327     function updateTags(tags) {
 
40328         wrap.selectAll('input')
 
40329             .value(function (field) {
 
40330                 return tags['addr:' + field.id] || '';
 
40334     address.entity = function(_) {
 
40335         if (!arguments.length) return entity;
 
40340     address.tags = function(tags) {
 
40341         if (isInitialized) {
 
40344             dispatch.on('init', function () {
 
40350     address.focus = function() {
 
40351         var node = wrap.selectAll('input').node();
 
40352         if (node) node.focus();
 
40355     return d3.rebind(address, dispatch, 'on');
 
40357 iD.ui.preset.check =
 
40358 iD.ui.preset.defaultcheck = function(field) {
 
40359     var dispatch = d3.dispatch('change'),
 
40360         options = field.strings && field.strings.options,
 
40363         entity, value, box, text, label;
 
40366         for (var k in options) {
 
40367             values.push(k === 'undefined' ? undefined : k);
 
40368             texts.push(field.t('options.' + k, { 'default': options[k] }));
 
40371         values = [undefined, 'yes'];
 
40372         texts = [t('inspector.unknown'), t('inspector.check.yes')];
 
40373         if (field.type === 'check') {
 
40375             texts.push(t('inspector.check.no'));
 
40379     var check = function(selection) {
 
40380         // hack: pretend oneway field is a oneway_yes field
 
40381         // where implied oneway tag exists (e.g. `junction=roundabout`) #2220, #1841
 
40382         if (field.id === 'oneway') {
 
40383             for (var key in entity.tags) {
 
40384                 if (key in iD.oneWayTags && (entity.tags[key] in iD.oneWayTags[key])) {
 
40385                     texts[0] = t('presets.fields.oneway_yes.options.undefined');
 
40391         selection.classed('checkselect', 'true');
 
40393         label = selection.selectAll('.preset-input-wrap')
 
40396         var enter = label.enter().append('label')
 
40397             .attr('class', 'preset-input-wrap');
 
40399         enter.append('input')
 
40400             .property('indeterminate', field.type === 'check')
 
40401             .attr('type', 'checkbox')
 
40402             .attr('id', 'preset-input-' + field.id);
 
40404         enter.append('span')
 
40406             .attr('class', 'value');
 
40408         box = label.select('input')
 
40409             .on('click', function() {
 
40411                 t[field.key] = values[(values.indexOf(value) + 1) % values.length];
 
40412                 dispatch.change(t);
 
40413                 d3.event.stopPropagation();
 
40416         text = label.select('span.value');
 
40419     check.entity = function(_) {
 
40420         if (!arguments.length) return entity;
 
40425     check.tags = function(tags) {
 
40426         value = tags[field.key];
 
40427         box.property('indeterminate', field.type === 'check' && !value);
 
40428         box.property('checked', value === 'yes');
 
40429         text.text(texts[values.indexOf(value)]);
 
40430         label.classed('set', !!value);
 
40433     check.focus = function() {
 
40434         box.node().focus();
 
40437     return d3.rebind(check, dispatch, 'on');
 
40439 iD.ui.preset.combo =
 
40440 iD.ui.preset.typeCombo =
 
40441 iD.ui.preset.multiCombo = function(field, context) {
 
40442     var dispatch = d3.dispatch('change'),
 
40443         isMulti = (field.type === 'multiCombo'),
 
40444         optstrings = field.strings && field.strings.options,
 
40445         optarray = field.options,
 
40446         snake_case = (field.snake_case || (field.snake_case === undefined)),
 
40447         combobox = d3.combobox().minItems(isMulti ? 1 : 2),
 
40454     // ensure multiCombo field.key ends with a ':'
 
40455     if (isMulti && field.key.match(/:$/) === null) {
 
40460     function snake(s) {
 
40461         return s.replace(/\s+/g, '_');
 
40464     function unsnake(s) {
 
40465         return s.replace(/_+/g, ' ');
 
40468     function clean(s) {
 
40469         return s.split(';')
 
40470             .map(function(s) { return s.trim(); })
 
40475     // returns the tag value for a display value
 
40476     // (for multiCombo, dval should be the key suffix, not the entire key)
 
40477     function tagValue(dval) {
 
40478         dval = clean(dval || '');
 
40481             var match = _.find(comboData, function(o) {
 
40482                 return o.key && clean(o.value) === dval;
 
40489         if (field.type === 'typeCombo' && !dval) {
 
40493         return (snake_case ? snake(dval) : dval) || undefined;
 
40497     // returns the display value for a tag value
 
40498     // (for multiCombo, tval should be the key suffix, not the entire key)
 
40499     function displayValue(tval) {
 
40503             var match = _.find(comboData, function(o) { return o.key === tval && o.value; });
 
40505                 return match.value;
 
40509         if (field.type === 'typeCombo' && tval.toLowerCase() === 'yes') {
 
40513         return snake_case ? unsnake(tval) : tval;
 
40517     function objectDifference(a, b) {
 
40518         return _.reject(a, function(d1) {
 
40519             return _.some(b, function(d2) { return d1.value === d2.value; });
 
40524     function initCombo(selection, attachTo) {
 
40526             selection.attr('readonly', 'readonly');
 
40527             selection.call(combobox, attachTo);
 
40528             setStaticValues(setPlaceholder);
 
40530         } else if (optarray) {
 
40531             selection.call(combobox, attachTo);
 
40532             setStaticValues(setPlaceholder);
 
40534         } else if (context.taginfo()) {
 
40535             selection.call(combobox.fetcher(setTaginfoValues), attachTo);
 
40536             setTaginfoValues('', setPlaceholder);
 
40541     function setStaticValues(callback) {
 
40542         if (!(optstrings || optarray)) return;
 
40545             comboData = Object.keys(optstrings).map(function(k) {
 
40546                 var v = field.t('options.' + k, { 'default': optstrings[k] });
 
40554         } else if (optarray) {
 
40555             comboData = optarray.map(function(k) {
 
40556                 var v = snake_case ? unsnake(k) : k;
 
40565         combobox.data(objectDifference(comboData, multiData));
 
40566         if (callback) callback(comboData);
 
40570     function setTaginfoValues(q, callback) {
 
40571         var fn = isMulti ? 'multikeys' : 'values';
 
40572         context.taginfo()[fn]({
 
40575             geometry: context.geometry(entity.id),
 
40576             query: (isMulti ? field.key : '') + q
 
40577         }, function(err, data) {
 
40579             comboData = _.map(data, 'value').map(function(k) {
 
40580                 if (isMulti) k = k.replace(field.key, '');
 
40581                 var v = snake_case ? unsnake(k) : k;
 
40588             comboData = objectDifference(comboData, multiData);
 
40589             if (callback) callback(comboData);
 
40594     function setPlaceholder(d) {
 
40597             ph = field.placeholder() || t('inspector.add');
 
40599             var vals = _.map(d, 'value').filter(function(s) { return s.length < 20; }),
 
40600                 placeholders = vals.length > 1 ? vals : _.map(d, 'key');
 
40601             ph = field.placeholder() || placeholders.slice(0, 3).join(', ');
 
40604         input.attr('placeholder', ph + '…');
 
40608     function change() {
 
40609         var val = tagValue(input.value()),
 
40614             container.classed('active', false);
 
40616             field.keys.push(field.key + val);
 
40617             t[field.key + val] = 'yes';
 
40618             window.setTimeout(function() { input.node().focus(); }, 10);
 
40621             t[field.key] = val;
 
40624         dispatch.change(t);
 
40628     function removeMultikey(d) {
 
40629         d3.event.stopPropagation();
 
40631         t[d.key] = undefined;
 
40632         dispatch.change(t);
 
40636     function combo(selection) {
 
40638             container = selection.selectAll('ul').data([0]);
 
40642                 .attr('class', 'form-field-multicombo')
 
40643                 .on('click', function() {
 
40644                     window.setTimeout(function() { input.node().focus(); }, 10);
 
40648             container = selection;
 
40651         input = container.selectAll('input')
 
40656             .attr('type', 'text')
 
40657             .attr('id', 'preset-input-' + field.id)
 
40658             .call(initCombo, selection);
 
40661             .on('change', change)
 
40662             .on('blur', change);
 
40666                 .on('accept', function() {
 
40667                     input.node().blur();
 
40668                     input.node().focus();
 
40672                 .on('focus', function() { container.classed('active', true); });
 
40677     combo.tags = function(tags) {
 
40681             // Build multiData array containing keys already set..
 
40682             Object.keys(tags).forEach(function(key) {
 
40683                 if (key.indexOf(field.key) !== 0 || tags[key].toLowerCase() !== 'yes') return;
 
40685                 var suffix = key.substring(field.key.length);
 
40688                     value: displayValue(suffix)
 
40692             // Set keys for form-field modified (needed for undo and reset buttons)..
 
40693             field.keys = _.map(multiData, 'key');
 
40695             // Exclude existing multikeys from combo options..
 
40696             var available = objectDifference(comboData, multiData);
 
40697             combobox.data(available);
 
40699             // Hide "Add" button if this field uses fixed set of
 
40700             // translateable optstrings and they're all currently used..
 
40701             container.selectAll('.combobox-input, .combobox-caret')
 
40702                 .classed('hide', optstrings && !available.length);
 
40706             var chips = container.selectAll('.chips').data(multiData);
 
40708             var enter = chips.enter()
 
40709                 .insert('li', 'input')
 
40710                 .attr('class', 'chips');
 
40712             enter.append('span');
 
40715             chips.select('span')
 
40716                 .text(function(d) { return d.value; });
 
40719                 .on('click', removeMultikey)
 
40720                 .attr('class', 'remove')
 
40727             input.value(displayValue(tags[field.key]));
 
40732     combo.focus = function() {
 
40733         input.node().focus();
 
40737     combo.entity = function(_) {
 
40738         if (!arguments.length) return entity;
 
40744     return d3.rebind(combo, dispatch, 'on');
 
40746 iD.ui.preset.cycleway = function(field) {
 
40747     var dispatch = d3.dispatch('change'),
 
40750     function cycleway(selection) {
 
40751         var wrap = selection.selectAll('.preset-input-wrap')
 
40754         wrap.enter().append('div')
 
40755             .attr('class', 'cf preset-input-wrap')
 
40758         items = wrap.select('ul').selectAll('li')
 
40763         var enter = items.enter().append('li')
 
40764             .attr('class', function(d) { return 'cf preset-cycleway-' + d; });
 
40766         enter.append('span')
 
40767             .attr('class', 'col6 label preset-label-cycleway')
 
40768             .attr('for', function(d) { return 'preset-input-cycleway-' + d; })
 
40769             .text(function(d) { return field.t('types.' + d); });
 
40771         enter.append('div')
 
40772             .attr('class', 'col6 preset-input-cycleway-wrap')
 
40774             .attr('type', 'text')
 
40775             .attr('class', 'preset-input-cycleway')
 
40776             .attr('id', function(d) { return 'preset-input-cycleway-' + d; })
 
40777             .each(function(d) {
 
40779                     .call(d3.combobox()
 
40780                         .data(cycleway.options(d)));
 
40785         wrap.selectAll('.preset-input-cycleway')
 
40786             .on('change', change)
 
40787             .on('blur', change);
 
40790     function change() {
 
40791         var inputs = d3.selectAll('.preset-input-cycleway')[0],
 
40792             left = d3.select(inputs[0]).value(),
 
40793             right = d3.select(inputs[1]).value(),
 
40795         if (left === 'none' || left === '') { left = undefined; }
 
40796         if (right === 'none' || right === '') { right = undefined; }
 
40798         // Always set both left and right as changing one can affect the other
 
40800             cycleway: undefined,
 
40801             'cycleway:left': left,
 
40802             'cycleway:right': right
 
40805         // If the left and right tags match, use the cycleway tag to tag both
 
40806         // sides the same way
 
40807         if (left === right) {
 
40810                 'cycleway:left': undefined,
 
40811                 'cycleway:right': undefined
 
40815         dispatch.change(tag);
 
40818     cycleway.options = function() {
 
40819         return d3.keys(field.strings.options).map(function(option) {
 
40821                 title: field.t('options.' + option + '.description'),
 
40827     cycleway.tags = function(tags) {
 
40828         items.selectAll('.preset-input-cycleway')
 
40829             .value(function(d) {
 
40830                 // If cycleway is set, always return that
 
40831                 if (tags.cycleway) {
 
40832                     return tags.cycleway;
 
40834                 return tags[d] || '';
 
40836             .attr('placeholder', field.placeholder());
 
40839     cycleway.focus = function() {
 
40840         items.selectAll('.preset-input-cycleway')
 
40844     return d3.rebind(cycleway, dispatch, 'on');
 
40846 iD.ui.preset.text =
 
40847 iD.ui.preset.number =
 
40849 iD.ui.preset.email =
 
40850 iD.ui.preset.url = function(field, context) {
 
40852     var dispatch = d3.dispatch('change'),
 
40856     function i(selection) {
 
40857         var fieldId = 'preset-input-' + field.id;
 
40859         input = selection.selectAll('input')
 
40862         input.enter().append('input')
 
40863             .attr('type', field.type)
 
40864             .attr('id', fieldId)
 
40865             .attr('placeholder', field.placeholder() || t('inspector.unknown'));
 
40868             .on('input', change(true))
 
40869             .on('blur', change())
 
40870             .on('change', change());
 
40872         if (field.type === 'tel') {
 
40873             var center = entity.extent(context.graph()).center();
 
40874             iD.services.nominatim().countryCode(center, function (err, countryCode) {
 
40875                 if (err || !iD.data.phoneFormats[countryCode]) return;
 
40876                 selection.selectAll('#' + fieldId)
 
40877                     .attr('placeholder', iD.data.phoneFormats[countryCode]);
 
40880         } else if (field.type === 'number') {
 
40881             input.attr('type', 'text');
 
40883             var spinControl = selection.selectAll('.spin-control')
 
40886             var enter = spinControl.enter().append('div')
 
40887                 .attr('class', 'spin-control');
 
40889             enter.append('button')
 
40891                 .attr('class', 'increment')
 
40892                 .attr('tabindex', -1);
 
40894             enter.append('button')
 
40896                 .attr('class', 'decrement')
 
40897                 .attr('tabindex', -1);
 
40899             spinControl.selectAll('button')
 
40900                 .on('click', function(d) {
 
40901                     d3.event.preventDefault();
 
40902                     var num = parseInt(input.node().value || 0, 10);
 
40903                     if (!isNaN(num)) input.node().value = num + d;
 
40909     function change(onInput) {
 
40910         return function() {
 
40912             t[field.key] = input.value() || undefined;
 
40913             dispatch.change(t, onInput);
 
40917     i.entity = function(_) {
 
40918         if (!arguments.length) return entity;
 
40923     i.tags = function(tags) {
 
40924         input.value(tags[field.key] || '');
 
40927     i.focus = function() {
 
40928         var node = input.node();
 
40929         if (node) node.focus();
 
40932     return d3.rebind(i, dispatch, 'on');
 
40934 iD.ui.preset.localized = function(field, context) {
 
40935     var dispatch = d3.dispatch('change', 'input'),
 
40936         wikipedia = iD.services.wikipedia(),
 
40937         input, localizedInputs, wikiTitles,
 
40940     function localized(selection) {
 
40941         input = selection.selectAll('.localized-main')
 
40944         input.enter().append('input')
 
40945             .attr('type', 'text')
 
40946             .attr('id', 'preset-input-' + field.id)
 
40947             .attr('class', 'localized-main')
 
40948             .attr('placeholder', field.placeholder());
 
40950         if (field.id === 'name') {
 
40951             var preset = context.presets().match(entity, context.graph());
 
40952             input.call(d3.combobox().fetcher(
 
40953                 iD.util.SuggestNames(preset, iD.data.suggestions)
 
40958             .on('input', change(true))
 
40959             .on('blur', change())
 
40960             .on('change', change());
 
40962         var translateButton = selection.selectAll('.localized-add')
 
40965         translateButton.enter()
 
40967             .attr('class', 'button-input-action localized-add minor')
 
40968             .attr('tabindex', -1)
 
40969             .call(iD.svg.Icon('#icon-plus'))
 
40970             .call(bootstrap.tooltip()
 
40971                 .title(t('translate.translate'))
 
40972                 .placement('left'));
 
40975             .on('click', addNew);
 
40977         localizedInputs = selection.selectAll('.localized-wrap')
 
40980         localizedInputs.enter().append('div')
 
40981             .attr('class', 'localized-wrap');
 
40984     function addNew() {
 
40985         d3.event.preventDefault();
 
40986         var data = localizedInputs.selectAll('div.entry').data();
 
40987         var defaultLang = iD.detect().locale.toLowerCase().split('-')[0];
 
40988         var langExists = _.find(data, function(datum) { return datum.lang === defaultLang;});
 
40989         var isLangEn = defaultLang.indexOf('en') > -1;
 
40990         if (isLangEn || langExists) {
 
40993         data.push({ lang: defaultLang, value: '' });
 
40994         localizedInputs.call(render, data);
 
40997     function change(onInput) {
 
40998         return function() {
 
41000             t[field.key] = d3.select(this).value() || undefined;
 
41001             dispatch.change(t, onInput);
 
41005     function key(lang) { return field.key + ':' + lang; }
 
41007     function changeLang(d) {
 
41008         var lang = d3.select(this).value(),
 
41010             language = _.find(iD.data.wikipedia, function(d) {
 
41011                 return d[0].toLowerCase() === lang.toLowerCase() ||
 
41012                     d[1].toLowerCase() === lang.toLowerCase();
 
41015         if (language) lang = language[2];
 
41017         if (d.lang && d.lang !== lang) {
 
41018             t[key(d.lang)] = undefined;
 
41021         var value = d3.select(this.parentNode)
 
41022             .selectAll('.localized-value')
 
41025         if (lang && value) {
 
41026             t[key(lang)] = value;
 
41027         } else if (lang && wikiTitles && wikiTitles[d.lang]) {
 
41028             t[key(lang)] = wikiTitles[d.lang];
 
41032         dispatch.change(t);
 
41035     function changeValue(d) {
 
41036         if (!d.lang) return;
 
41038         t[key(d.lang)] = d3.select(this).value() || undefined;
 
41039         dispatch.change(t);
 
41042     function fetcher(value, cb) {
 
41043         var v = value.toLowerCase();
 
41045         cb(iD.data.wikipedia.filter(function(d) {
 
41046             return d[0].toLowerCase().indexOf(v) >= 0 ||
 
41047             d[1].toLowerCase().indexOf(v) >= 0 ||
 
41048             d[2].toLowerCase().indexOf(v) >= 0;
 
41049         }).map(function(d) {
 
41050             return { value: d[1] };
 
41054     function render(selection, data) {
 
41055         var wraps = selection.selectAll('div.entry').
 
41056             data(data, function(d) { return d.lang; });
 
41058         var innerWrap = wraps.enter()
 
41059             .insert('div', ':first-child');
 
41061         innerWrap.attr('class', 'entry')
 
41063                 var wrap = d3.select(this);
 
41064                 var langcombo = d3.combobox().fetcher(fetcher).minItems(0);
 
41066                 var label = wrap.append('label')
 
41067                     .attr('class','form-label')
 
41068                     .text(t('translate.localized_translation_label'))
 
41069                     .attr('for','localized-lang');
 
41071                 label.append('button')
 
41072                     .attr('class', 'minor remove')
 
41073                     .on('click', function(d){
 
41074                         d3.event.preventDefault();
 
41076                         t[key(d.lang)] = undefined;
 
41077                         dispatch.change(t);
 
41078                         d3.select(this.parentNode.parentNode)
 
41080                             .style('max-height','240px')
 
41082                             .style('opacity', '0')
 
41083                             .style('max-height','0px')
 
41086                     .call(iD.svg.Icon('#operation-delete'));
 
41088                 wrap.append('input')
 
41089                     .attr('class', 'localized-lang')
 
41090                     .attr('type', 'text')
 
41091                     .attr('placeholder',t('translate.localized_translation_language'))
 
41092                     .on('blur', changeLang)
 
41093                     .on('change', changeLang)
 
41096                 wrap.append('input')
 
41097                     .on('blur', changeValue)
 
41098                     .on('change', changeValue)
 
41099                     .attr('type', 'text')
 
41100                     .attr('placeholder', t('translate.localized_translation_name'))
 
41101                     .attr('class', 'localized-value');
 
41105             .style('margin-top', '0px')
 
41106             .style('max-height', '0px')
 
41107             .style('opacity', '0')
 
41110             .style('margin-top', '10px')
 
41111             .style('max-height', '240px')
 
41112             .style('opacity', '1')
 
41113             .each('end', function() {
 
41115                     .style('max-height', '')
 
41116                     .style('overflow', 'visible');
 
41122             .style('max-height','0px')
 
41123             .style('opacity', '0')
 
41124             .style('top','-10px')
 
41127         var entry = selection.selectAll('.entry');
 
41129         entry.select('.localized-lang')
 
41130             .value(function(d) {
 
41131                 var lang = _.find(iD.data.wikipedia, function(lang) { return lang[2] === d.lang; });
 
41132                 return lang ? lang[1] : d.lang;
 
41135         entry.select('.localized-value')
 
41136             .value(function(d) { return d.value; });
 
41139     localized.tags = function(tags) {
 
41140         // Fetch translations from wikipedia
 
41141         if (tags.wikipedia && !wikiTitles) {
 
41143             var wm = tags.wikipedia.match(/([^:]+):(.+)/);
 
41144             if (wm && wm[0] && wm[1]) {
 
41145                 wikipedia.translations(wm[1], wm[2], function(d) {
 
41151         input.value(tags[field.key] || '');
 
41153         var postfixed = [], k, m;
 
41155             m = k.match(/^(.*):([a-zA-Z_-]+)$/);
 
41156             if (m && m[1] === field.key && m[2]) {
 
41157                 postfixed.push({ lang: m[2], value: tags[k] });
 
41161         localizedInputs.call(render, postfixed.reverse());
 
41164     localized.focus = function() {
 
41165         input.node().focus();
 
41168     localized.entity = function(_) {
 
41169         if (!arguments.length) return entity;
 
41174     return d3.rebind(localized, dispatch, 'on');
 
41176 iD.ui.preset.maxspeed = function(field, context) {
 
41177     var dispatch = d3.dispatch('change'),
 
41184     var metricValues = [20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
 
41185         imperialValues = [20, 25, 30, 35, 40, 45, 50, 55, 65, 70];
 
41187     function maxspeed(selection) {
 
41188         combobox = d3.combobox();
 
41189         var unitCombobox = d3.combobox().data(['km/h', 'mph'].map(comboValues));
 
41191         input = selection.selectAll('#preset-input-' + field.id)
 
41194         input.enter().append('input')
 
41195             .attr('type', 'text')
 
41196             .attr('id', 'preset-input-' + field.id)
 
41197             .attr('placeholder', field.placeholder());
 
41201             .on('change', change)
 
41202             .on('blur', change);
 
41204         var childNodes = context.graph().childNodes(context.entity(entity.id)),
 
41205             loc = childNodes[~~(childNodes.length/2)].loc;
 
41207         imperial = _.some(iD.data.imperial.features, function(f) {
 
41208             return _.some(f.geometry.coordinates, function(d) {
 
41209                 return iD.geo.pointInPolygon(loc, d);
 
41213         unitInput = selection.selectAll('input.maxspeed-unit')
 
41216         unitInput.enter().append('input')
 
41217             .attr('type', 'text')
 
41218             .attr('class', 'maxspeed-unit');
 
41221             .on('blur', changeUnits)
 
41222             .on('change', changeUnits)
 
41223             .call(unitCombobox);
 
41225         function changeUnits() {
 
41226             imperial = unitInput.value() === 'mph';
 
41227             unitInput.value(imperial ? 'mph' : 'km/h');
 
41234     function setSuggestions() {
 
41235         combobox.data((imperial ? imperialValues : metricValues).map(comboValues));
 
41236         unitInput.value(imperial ? 'mph' : 'km/h');
 
41239     function comboValues(d) {
 
41241             value: d.toString(),
 
41242             title: d.toString()
 
41246     function change() {
 
41248             value = input.value();
 
41251             tag[field.key] = undefined;
 
41252         } else if (isNaN(value) || !imperial) {
 
41253             tag[field.key] = value;
 
41255             tag[field.key] = value + ' mph';
 
41258         dispatch.change(tag);
 
41261     maxspeed.tags = function(tags) {
 
41262         var value = tags[field.key];
 
41264         if (value && value.indexOf('mph') >= 0) {
 
41265             value = parseInt(value, 10);
 
41267         } else if (value) {
 
41273         input.value(value || '');
 
41276     maxspeed.focus = function() {
 
41277         input.node().focus();
 
41280     maxspeed.entity = function(_) {
 
41284     return d3.rebind(maxspeed, dispatch, 'on');
 
41286 iD.ui.preset.radio = function(field) {
 
41287     var dispatch = d3.dispatch('change'),
 
41288         labels, radios, placeholder;
 
41290     function radio(selection) {
 
41291         selection.classed('preset-radio', true);
 
41293         var wrap = selection.selectAll('.preset-input-wrap')
 
41296         var buttonWrap = wrap.enter().append('div')
 
41297             .attr('class', 'preset-input-wrap toggle-list');
 
41299         buttonWrap.append('span')
 
41300             .attr('class', 'placeholder');
 
41302         placeholder = selection.selectAll('.placeholder');
 
41304         labels = wrap.selectAll('label')
 
41305             .data(field.options || field.keys);
 
41307         var enter = labels.enter().append('label');
 
41309         enter.append('input')
 
41310             .attr('type', 'radio')
 
41311             .attr('name', field.id)
 
41312             .attr('value', function(d) { return field.t('options.' + d, { 'default': d }); })
 
41313             .attr('checked', false);
 
41315         enter.append('span')
 
41316             .text(function(d) { return field.t('options.' + d, { 'default': d }); });
 
41318         radios = labels.selectAll('input')
 
41319             .on('change', change);
 
41322     function change() {
 
41324         if (field.key) t[field.key] = undefined;
 
41325         radios.each(function(d) {
 
41326             var active = d3.select(this).property('checked');
 
41328                 if (active) t[field.key] = d;
 
41330                 t[d] = active ? 'yes' : undefined;
 
41333         dispatch.change(t);
 
41336     radio.tags = function(tags) {
 
41337         function checked(d) {
 
41339                 return tags[field.key] === d;
 
41341                 return !!(tags[d] && tags[d] !== 'no');
 
41345         labels.classed('active', checked);
 
41346         radios.property('checked', checked);
 
41347         var selection = radios.filter(function() { return this.checked; });
 
41348         if (selection.empty()) {
 
41349             placeholder.text(t('inspector.none'));
 
41351             placeholder.text(selection.attr('value'));
 
41355     radio.focus = function() {
 
41356         radios.node().focus();
 
41359     return d3.rebind(radio, dispatch, 'on');
 
41361 iD.ui.preset.restrictions = function(field, context) {
 
41362     var dispatch = d3.dispatch('change'),
 
41363         hover = iD.behavior.Hover(context),
 
41368     function restrictions(selection) {
 
41369         // if form field is hidden or has detached from dom, clean up.
 
41370         if (!d3.select('.inspector-wrap.inspector-hidden').empty() || !selection.node().parentNode) {
 
41371             selection.call(restrictions.off);
 
41375         var wrap = selection.selectAll('.preset-input-wrap')
 
41378         var enter = wrap.enter()
 
41380             .attr('class', 'preset-input-wrap');
 
41384             .attr('class', 'restriction-help');
 
41387         var intersection = iD.geo.Intersection(context.graph(), vertexID),
 
41388             graph = intersection.graph,
 
41389             vertex = graph.entity(vertexID),
 
41390             filter = d3.functor(true),
 
41391             extent = iD.geo.Extent(),
 
41392             projection = iD.geo.RawMercator();
 
41394         var d = wrap.dimensions(),
 
41395             c = [d[0] / 2, d[1] / 2],
 
41399             .scale(256 * Math.pow(2, z) / (2 * Math.PI));
 
41401         var s = projection(vertex.loc);
 
41404             .translate([c[0] - s[0], c[1] - s[1]])
 
41405             .clipExtent([[0, 0], d]);
 
41407         var drawLayers = iD.svg.Layers(projection, context).only('osm').dimensions(d),
 
41408             drawVertices = iD.svg.Vertices(projection, context),
 
41409             drawLines = iD.svg.Lines(projection, context),
 
41410             drawTurns = iD.svg.Turns(projection, context);
 
41414             .selectAll('.surface')
 
41418         var surface = wrap.selectAll('.surface');
 
41422             .call(drawVertices, graph, [vertex], filter, extent, z)
 
41423             .call(drawLines, graph, intersection.ways, filter)
 
41424             .call(drawTurns, graph, intersection.turns(fromNodeID));
 
41427             .on('click.restrictions', click)
 
41428             .on('mouseover.restrictions', mouseover)
 
41429             .on('mouseout.restrictions', mouseout);
 
41432             .selectAll('.selected')
 
41433             .classed('selected', false);
 
41437                 .selectAll('.' + intersection.highways[fromNodeID].id)
 
41438                 .classed('selected', true);
 
41444             .on('change.restrictions', render);
 
41447             .on('resize.restrictions', function() {
 
41448                 wrap.dimensions(null);
 
41453             var datum = d3.event.target.__data__;
 
41454             if (datum instanceof iD.Entity) {
 
41455                 fromNodeID = intersection.adjacentNodeId(datum.id);
 
41457             } else if (datum instanceof iD.geo.Turn) {
 
41458                 if (datum.restriction) {
 
41460                         iD.actions.UnrestrictTurn(datum, projection),
 
41461                         t('operations.restriction.annotation.delete'));
 
41464                         iD.actions.RestrictTurn(datum, projection),
 
41465                         t('operations.restriction.annotation.create'));
 
41470         function mouseover() {
 
41471             var datum = d3.event.target.__data__;
 
41472             if (datum instanceof iD.geo.Turn) {
 
41473                 var graph = context.graph(),
 
41474                     presets = context.presets(),
 
41477                 if (datum.restriction) {
 
41478                     preset = presets.match(graph.entity(datum.restriction), graph);
 
41480                     preset = presets.item('type/restriction/' +
 
41481                         iD.geo.inferRestriction(
 
41489                 wrap.selectAll('.restriction-help')
 
41490                     .text(t('operations.restriction.help.' +
 
41491                         (datum.restriction ? 'toggle_off' : 'toggle_on'),
 
41492                         {restriction: preset.name()}));
 
41496         function mouseout() {
 
41497             wrap.selectAll('.restriction-help')
 
41498                 .text(t('operations.restriction.help.' +
 
41499                     (fromNodeID ? 'toggle' : 'select')));
 
41502         function render() {
 
41503             if (context.hasEntity(vertexID)) {
 
41504                 restrictions(selection);
 
41509     restrictions.entity = function(_) {
 
41510         if (!vertexID || vertexID !== _.id) {
 
41516     restrictions.tags = function() {};
 
41517     restrictions.focus = function() {};
 
41519     restrictions.off = function(selection) {
 
41520         selection.selectAll('.surface')
 
41522             .on('click.restrictions', null)
 
41523             .on('mouseover.restrictions', null)
 
41524             .on('mouseout.restrictions', null);
 
41527             .on('change.restrictions', null);
 
41530             .on('resize.restrictions', null);
 
41533     return d3.rebind(restrictions, dispatch, 'on');
 
41535 iD.ui.preset.textarea = function(field) {
 
41536     var dispatch = d3.dispatch('change'),
 
41539     function textarea(selection) {
 
41540         input = selection.selectAll('textarea')
 
41543         input.enter().append('textarea')
 
41544             .attr('id', 'preset-input-' + field.id)
 
41545             .attr('placeholder', field.placeholder() || t('inspector.unknown'))
 
41546             .attr('maxlength', 255);
 
41549             .on('input', change(true))
 
41550             .on('blur', change())
 
41551             .on('change', change());
 
41554     function change(onInput) {
 
41555         return function() {
 
41557             t[field.key] = input.value() || undefined;
 
41558             dispatch.change(t, onInput);
 
41562     textarea.tags = function(tags) {
 
41563         input.value(tags[field.key] || '');
 
41566     textarea.focus = function() {
 
41567         input.node().focus();
 
41570     return d3.rebind(textarea, dispatch, 'on');
 
41572 iD.ui.preset.wikipedia = function(field, context) {
 
41573     var dispatch = d3.dispatch('change'),
 
41574         wikipedia = iD.services.wikipedia(),
 
41575         wikidata = iD.services.wikidata(),
 
41576         link, entity, lang, title;
 
41578     function wiki(selection) {
 
41579         var langcombo = d3.combobox()
 
41580             .fetcher(function(value, cb) {
 
41581                 var v = value.toLowerCase();
 
41583                 cb(iD.data.wikipedia.filter(function(d) {
 
41584                     return d[0].toLowerCase().indexOf(v) >= 0 ||
 
41585                         d[1].toLowerCase().indexOf(v) >= 0 ||
 
41586                         d[2].toLowerCase().indexOf(v) >= 0;
 
41587                 }).map(function(d) {
 
41588                     return { value: d[1] };
 
41592         var titlecombo = d3.combobox()
 
41593             .fetcher(function(value, cb) {
 
41595                 if (!value) value = context.entity(entity.id).tags.name || '';
 
41596                 var searchfn = value.length > 7 ? wikipedia.search : wikipedia.suggestions;
 
41598                 searchfn(language()[2], value, function(query, data) {
 
41599                     cb(data.map(function(d) {
 
41600                         return { value: d };
 
41605         lang = selection.selectAll('input.wiki-lang')
 
41608         lang.enter().append('input')
 
41609             .attr('type', 'text')
 
41610             .attr('class', 'wiki-lang')
 
41611             .attr('placeholder', t('translate.localized_translation_language'))
 
41616             .on('blur', changeLang)
 
41617             .on('change', changeLang);
 
41619         title = selection.selectAll('input.wiki-title')
 
41622         title.enter().append('input')
 
41623             .attr('type', 'text')
 
41624             .attr('class', 'wiki-title')
 
41625             .attr('id', 'preset-input-' + field.id);
 
41630             .on('change', change);
 
41632         link = selection.selectAll('a.wiki-link')
 
41635         link.enter().append('a')
 
41636             .attr('class', 'wiki-link button-input-action minor')
 
41637             .attr('tabindex', -1)
 
41638             .attr('target', '_blank')
 
41639             .call(iD.svg.Icon('#icon-out-link', 'inline'));
 
41642     function language() {
 
41643         var value = lang.value().toLowerCase();
 
41644         var locale = iD.detect().locale.toLowerCase();
 
41645         var localeLanguage;
 
41646         return _.find(iD.data.wikipedia, function(d) {
 
41647             if (d[2] === locale) localeLanguage = d;
 
41648             return d[0].toLowerCase() === value ||
 
41649                 d[1].toLowerCase() === value ||
 
41651         }) || localeLanguage || ['English', 'English', 'en'];
 
41654     function changeLang() {
 
41655         lang.value(language()[1]);
 
41663     function change(skipWikidata) {
 
41664         var value = title.value(),
 
41665             m = value.match(/https?:\/\/([-a-z]+)\.wikipedia\.org\/(?:wiki|\1-[-a-z]+)\/([^#]+)(?:#(.+))?/),
 
41666             l = m && _.find(iD.data.wikipedia, function(d) { return m[1] === d[2]; }),
 
41671             // Normalize title http://www.mediawiki.org/wiki/API:Query#Title_normalization
 
41672             value = decodeURIComponent(m[2]).replace(/_/g, ' ');
 
41675                     // Best-effort `anchordecode:` implementation
 
41676                     anchor = decodeURIComponent(m[3].replace(/\.([0-9A-F]{2})/g, '%$1'));
 
41678                     anchor = decodeURIComponent(m[3]);
 
41680                 value += '#' + anchor.replace(/_/g, ' ');
 
41682             value = value.slice(0, 1).toUpperCase() + value.slice(1);
 
41684             title.value(value);
 
41687         syncTags.wikipedia = value ? language()[2] + ':' + value : undefined;
 
41688         if (!skipWikidata) {
 
41689             syncTags.wikidata = undefined;
 
41692         dispatch.change(syncTags);
 
41695         if (skipWikidata || !value || !language()[2]) return;
 
41697         // attempt asynchronous update of wikidata tag..
 
41698         var initEntityId = entity.id,
 
41699             initWikipedia = context.entity(initEntityId).tags.wikipedia;
 
41701         wikidata.itemsByTitle(language()[2], value, function (title, data) {
 
41702             // 1. most recent change was a tag change
 
41703             var annotation = t('operations.change_tags.annotation'),
 
41704                 currAnnotation = context.history().undoAnnotation();
 
41705             if (currAnnotation !== annotation) return;
 
41707             // 2. same entity exists and still selected
 
41708             var selectedIds = context.selectedIDs(),
 
41709                 currEntityId = selectedIds.length > 0 && selectedIds[0];
 
41710             if (currEntityId !== initEntityId) return;
 
41712             // 3. wikipedia value has not changed
 
41713             var currTags = _.clone(context.entity(currEntityId).tags),
 
41714                 qids = data && Object.keys(data);
 
41715             if (initWikipedia !== currTags.wikipedia) return;
 
41717             // ok to coalesce the update of wikidata tag into the previous tag change
 
41718             currTags.wikidata = qids && _.find(qids, function (id) {
 
41719                 return id.match(/^Q\d+$/);
 
41722             context.overwrite(iD.actions.ChangeTags(currEntityId, currTags), annotation);
 
41723             dispatch.change(currTags);
 
41727     wiki.tags = function(tags) {
 
41728         var value = tags[field.key] || '',
 
41729             m = value.match(/([^:]+):([^#]+)(?:#(.+))?/),
 
41730             l = m && _.find(iD.data.wikipedia, function(d) { return m[1] === d[2]; }),
 
41731             anchor = m && m[3];
 
41733         // value in correct format
 
41736             title.value(m[2] + (anchor ? ('#' + anchor) : ''));
 
41739                     // Best-effort `anchorencode:` implementation
 
41740                     anchor = encodeURIComponent(anchor.replace(/ /g, '_')).replace(/%/g, '.');
 
41742                     anchor = anchor.replace(/ /g, '_');
 
41745             link.attr('href', 'https://' + m[1] + '.wikipedia.org/wiki/' +
 
41746                 m[2].replace(/ /g, '_') + (anchor ? ('#' + anchor) : ''));
 
41748         // unrecognized value format
 
41750             title.value(value);
 
41751             if (value && value !== '') {
 
41754             link.attr('href', 'https://en.wikipedia.org/wiki/Special:Search?search=' + value);
 
41758     wiki.entity = function(_) {
 
41759         if (!arguments.length) return entity;
 
41764     wiki.focus = function() {
 
41765         title.node().focus();
 
41768     return d3.rebind(wiki, dispatch, 'on');
 
41770 iD.ui.intro.area = function(context, reveal) {
 
41771     var event = d3.dispatch('done'),
 
41775         title: 'intro.areas.title'
 
41778     step.enter = function() {
 
41779         var playground = [-85.63552, 41.94159],
 
41780             corner = [-85.63565411045074, 41.9417715536927];
 
41781         context.map().centerZoom(playground, 19);
 
41782         reveal('button.add-area',
 
41783             t('intro.areas.add', { button: iD.ui.intro.icon('#icon-area', 'pre-text') }),
 
41784             { tooltipClass: 'intro-areas-add' });
 
41786         context.on('enter.intro', addArea);
 
41788         function addArea(mode) {
 
41789             if (mode.id !== 'add-area') return;
 
41790             context.on('enter.intro', drawArea);
 
41792             var padding = 120 * Math.pow(2, context.map().zoom() - 19);
 
41793             var pointBox = iD.ui.intro.pad(corner, padding, context);
 
41794             reveal(pointBox, t('intro.areas.corner'));
 
41796             context.map().on('move.intro', function() {
 
41797                 padding = 120 * Math.pow(2, context.map().zoom() - 19);
 
41798                 pointBox = iD.ui.intro.pad(corner, padding, context);
 
41799                 reveal(pointBox, t('intro.areas.corner'), {duration: 0});
 
41803         function drawArea(mode) {
 
41804             if (mode.id !== 'draw-area') return;
 
41805             context.on('enter.intro', enterSelect);
 
41807             var padding = 150 * Math.pow(2, context.map().zoom() - 19);
 
41808             var pointBox = iD.ui.intro.pad(playground, padding, context);
 
41809             reveal(pointBox, t('intro.areas.place'));
 
41811             context.map().on('move.intro', function() {
 
41812                 padding = 150 * Math.pow(2, context.map().zoom() - 19);
 
41813                 pointBox = iD.ui.intro.pad(playground, padding, context);
 
41814                 reveal(pointBox, t('intro.areas.place'), {duration: 0});
 
41818         function enterSelect(mode) {
 
41819             if (mode.id !== 'select') return;
 
41820             context.map().on('move.intro', null);
 
41821             context.on('enter.intro', null);
 
41823             timeout = setTimeout(function() {
 
41824                 reveal('.preset-search-input',
 
41825                     t('intro.areas.search',
 
41826                     { name: context.presets().item('leisure/playground').name() }));
 
41827                 d3.select('.preset-search-input').on('keyup.intro', keySearch);
 
41831         function keySearch() {
 
41832             var first = d3.select('.preset-list-item:first-child');
 
41833             if (first.classed('preset-leisure-playground')) {
 
41834                 reveal(first.select('.preset-list-button').node(), t('intro.areas.choose'));
 
41835                 d3.selection.prototype.one.call(context.history(), 'change.intro', selectedPreset);
 
41836                 d3.select('.preset-search-input').on('keyup.intro', null);
 
41840         function selectedPreset() {
 
41842                 t('intro.areas.describe', { button: iD.ui.intro.icon('#icon-apply', 'pre-text') }));
 
41843             context.on('exit.intro', event.done);
 
41847     step.exit = function() {
 
41848         window.clearTimeout(timeout);
 
41849         context.on('enter.intro', null);
 
41850         context.on('exit.intro', null);
 
41851         context.history().on('change.intro', null);
 
41852         context.map().on('move.intro', null);
 
41853         d3.select('.preset-search-input').on('keyup.intro', null);
 
41856     return d3.rebind(step, event, 'on');
 
41858 iD.ui.intro.line = function(context, reveal) {
 
41859     var event = d3.dispatch('done'),
 
41863         title: 'intro.lines.title'
 
41866     function timeout(f, t) {
 
41867         timeouts.push(window.setTimeout(f, t));
 
41870     function eventCancel() {
 
41871         d3.event.stopPropagation();
 
41872         d3.event.preventDefault();
 
41875     step.enter = function() {
 
41876         var centroid = [-85.62830, 41.95699];
 
41877         var midpoint = [-85.62975395449628, 41.95787501510204];
 
41878         var start = [-85.6297754121684, 41.95805253325314];
 
41879         var intersection = [-85.62974496187628, 41.95742515554585];
 
41881         context.map().centerZoom(start, 18);
 
41882         reveal('button.add-line',
 
41883             t('intro.lines.add', { button: iD.ui.intro.icon('#icon-line', 'pre-text') }),
 
41884             { tooltipClass: 'intro-lines-add' });
 
41886         context.on('enter.intro', addLine);
 
41888         function addLine(mode) {
 
41889             if (mode.id !== 'add-line') return;
 
41890             context.on('enter.intro', drawLine);
 
41892             var padding = 150 * Math.pow(2, context.map().zoom() - 18);
 
41893             var pointBox = iD.ui.intro.pad(start, padding, context);
 
41894             reveal(pointBox, t('intro.lines.start'));
 
41896             context.map().on('move.intro', function() {
 
41897                 padding = 150 * Math.pow(2, context.map().zoom() - 18);
 
41898                 pointBox = iD.ui.intro.pad(start, padding, context);
 
41899                 reveal(pointBox, t('intro.lines.start'), {duration: 0});
 
41903         function drawLine(mode) {
 
41904             if (mode.id !== 'draw-line') return;
 
41905             context.history().on('change.intro', addIntersection);
 
41906             context.on('enter.intro', retry);
 
41908             var padding = 300 * Math.pow(2, context.map().zoom() - 19);
 
41909             var pointBox = iD.ui.intro.pad(midpoint, padding, context);
 
41910             reveal(pointBox, t('intro.lines.intersect', {name: t('intro.graph.flower_st')}));
 
41912             context.map().on('move.intro', function() {
 
41913                 padding = 300 * Math.pow(2, context.map().zoom() - 19);
 
41914                 pointBox = iD.ui.intro.pad(midpoint, padding, context);
 
41915                 reveal(pointBox, t('intro.lines.intersect', {name: t('intro.graph.flower_st')}), {duration: 0});
 
41919         // ended line before creating intersection
 
41920         function retry(mode) {
 
41921             if (mode.id !== 'select') return;
 
41922             var pointBox = iD.ui.intro.pad(intersection, 30, context),
 
41923                 ids = mode.selectedIDs();
 
41924             reveal(pointBox, t('intro.lines.restart', {name: t('intro.graph.flower_st')}));
 
41925             d3.select(window).on('mousedown.intro', eventCancel, true);
 
41927             timeout(function() {
 
41928                 context.replace(iD.actions.DeleteMultiple(ids));
 
41934         function addIntersection(changes) {
 
41935             if ( _.some(changes.created(), function(d) {
 
41936                 return d.type === 'node' && context.graph().parentWays(d).length > 1;
 
41938                 context.history().on('change.intro', null);
 
41939                 context.on('enter.intro', enterSelect);
 
41941                 var padding = 900 * Math.pow(2, context.map().zoom() - 19);
 
41942                 var pointBox = iD.ui.intro.pad(centroid, padding, context);
 
41943                 reveal(pointBox, t('intro.lines.finish'));
 
41945                 context.map().on('move.intro', function() {
 
41946                     padding = 900 * Math.pow(2, context.map().zoom() - 19);
 
41947                     pointBox = iD.ui.intro.pad(centroid, padding, context);
 
41948                     reveal(pointBox, t('intro.lines.finish'), {duration: 0});
 
41953         function enterSelect(mode) {
 
41954             if (mode.id !== 'select') return;
 
41955             context.map().on('move.intro', null);
 
41956             context.on('enter.intro', null);
 
41957             d3.select('#curtain').style('pointer-events', 'all');
 
41962         function presetCategory() {
 
41963             timeout(function() {
 
41964                 d3.select('#curtain').style('pointer-events', 'none');
 
41965                 var road = d3.select('.preset-category-road .preset-list-button');
 
41966                 reveal(road.node(), t('intro.lines.road'));
 
41967                 road.one('click.intro', roadCategory);
 
41971         function roadCategory() {
 
41972             timeout(function() {
 
41973                 var grid = d3.select('.subgrid');
 
41974                 reveal(grid.node(), t('intro.lines.residential'));
 
41975                 grid.selectAll(':not(.preset-highway-residential) .preset-list-button')
 
41976                     .one('click.intro', retryPreset);
 
41977                 grid.selectAll('.preset-highway-residential .preset-list-button')
 
41978                     .one('click.intro', roadDetails);
 
41982         // selected wrong road type
 
41983         function retryPreset() {
 
41984             timeout(function() {
 
41985                 var preset = d3.select('.entity-editor-pane .preset-list-button');
 
41986                 reveal(preset.node(), t('intro.lines.wrong_preset'));
 
41987                 preset.one('click.intro', presetCategory);
 
41991         function roadDetails() {
 
41993                 t('intro.lines.describe', { button: iD.ui.intro.icon('#icon-apply', 'pre-text') }));
 
41994             context.on('exit.intro', event.done);
 
41999     step.exit = function() {
 
42000         d3.select(window).on('mousedown.intro', null, true);
 
42001         d3.select('#curtain').style('pointer-events', 'none');
 
42002         timeouts.forEach(window.clearTimeout);
 
42003         context.on('enter.intro', null);
 
42004         context.on('exit.intro', null);
 
42005         context.map().on('move.intro', null);
 
42006         context.history().on('change.intro', null);
 
42009     return d3.rebind(step, event, 'on');
 
42011 iD.ui.intro.navigation = function(context, reveal) {
 
42012     var event = d3.dispatch('done'),
 
42016         title: 'intro.navigation.title'
 
42019     function set(f, t) {
 
42020         timeouts.push(window.setTimeout(f, t));
 
42023     function eventCancel() {
 
42024         d3.event.stopPropagation();
 
42025         d3.event.preventDefault();
 
42028     step.enter = function() {
 
42029         var rect = context.surfaceRect(),
 
42031                 left: rect.left + 10,
 
42032                 top: rect.top + 70,
 
42033                 width: rect.width - 70,
 
42034                 height: rect.height - 170
 
42037         context.map().centerZoom([-85.63591, 41.94285], 19);
 
42039         reveal(map, t('intro.navigation.drag'));
 
42041         context.map().on('move.intro', _.debounce(function() {
 
42042             context.map().on('move.intro', null);
 
42044             context.on('enter.intro', inspectTownHall);
 
42047         function townhall() {
 
42048             var hall = [-85.63645945147184, 41.942986488012565];
 
42050             var point = context.projection(hall);
 
42051             if (point[0] < 0 || point[0] > rect.width ||
 
42052                 point[1] < 0 || point[1] > rect.height) {
 
42053                 context.map().center(hall);
 
42056             var box = iD.ui.intro.pointBox(hall, context);
 
42057             reveal(box, t('intro.navigation.select'));
 
42059             context.map().on('move.intro', function() {
 
42060                 var box = iD.ui.intro.pointBox(hall, context);
 
42061                 reveal(box, t('intro.navigation.select'), {duration: 0});
 
42065         function inspectTownHall(mode) {
 
42066             if (mode.id !== 'select') return;
 
42067             context.on('enter.intro', null);
 
42068             context.map().on('move.intro', null);
 
42070                 reveal('.entity-editor-pane',
 
42071                     t('intro.navigation.pane', { button: iD.ui.intro.icon('#icon-close', 'pre-text') }));
 
42072                 context.on('exit.intro', streetSearch);
 
42076         function streetSearch() {
 
42077             context.on('exit.intro', null);
 
42078             reveal('.search-header input',
 
42079                 t('intro.navigation.search', { name: t('intro.graph.spring_st') }));
 
42080             d3.select('.search-header input').on('keyup.intro', searchResult);
 
42083         function searchResult() {
 
42084             var first = d3.select('.feature-list-item:nth-child(0n+2)'),  // skip No Results item
 
42085                 firstName = first.select('.entity-name'),
 
42086                 name = t('intro.graph.spring_st');
 
42088             if (!firstName.empty() && firstName.text() === name) {
 
42089                 reveal(first.node(), t('intro.navigation.choose', { name: name }));
 
42090                 context.on('exit.intro', selectedStreet);
 
42091                 d3.select('.search-header input')
 
42092                     .on('keydown.intro', eventCancel, true)
 
42093                     .on('keyup.intro', null);
 
42097         function selectedStreet() {
 
42098             var springSt = [-85.63585099140167, 41.942506848938926];
 
42099             context.map().center(springSt);
 
42100             context.on('exit.intro', event.done);
 
42102                 reveal('.entity-editor-pane',
 
42103                     t('intro.navigation.chosen', {
 
42104                         name: t('intro.graph.spring_st'),
 
42105                         button: iD.ui.intro.icon('#icon-close', 'pre-text')
 
42111     step.exit = function() {
 
42112         timeouts.forEach(window.clearTimeout);
 
42113         context.map().on('move.intro', null);
 
42114         context.on('enter.intro', null);
 
42115         context.on('exit.intro', null);
 
42116         d3.select('.search-header input')
 
42117             .on('keydown.intro', null)
 
42118             .on('keyup.intro', null);
 
42121     return d3.rebind(step, event, 'on');
 
42123 iD.ui.intro.point = function(context, reveal) {
 
42124     var event = d3.dispatch('done'),
 
42128         title: 'intro.points.title'
 
42131     function setTimeout(f, t) {
 
42132         timeouts.push(window.setTimeout(f, t));
 
42135     function eventCancel() {
 
42136         d3.event.stopPropagation();
 
42137         d3.event.preventDefault();
 
42140     step.enter = function() {
 
42141         context.map().centerZoom([-85.63279, 41.94394], 19);
 
42142         reveal('button.add-point',
 
42143             t('intro.points.add', { button: iD.ui.intro.icon('#icon-point', 'pre-text') }),
 
42144             { tooltipClass: 'intro-points-add' });
 
42146         var corner = [-85.632481,41.944094];
 
42148         context.on('enter.intro', addPoint);
 
42150         function addPoint(mode) {
 
42151             if (mode.id !== 'add-point') return;
 
42152             context.on('enter.intro', enterSelect);
 
42154             var pointBox = iD.ui.intro.pad(corner, 150, context);
 
42155             reveal(pointBox, t('intro.points.place'));
 
42157             context.map().on('move.intro', function() {
 
42158                 pointBox = iD.ui.intro.pad(corner, 150, context);
 
42159                 reveal(pointBox, t('intro.points.place'), {duration: 0});
 
42163         function enterSelect(mode) {
 
42164             if (mode.id !== 'select') return;
 
42165             context.map().on('move.intro', null);
 
42166             context.on('enter.intro', null);
 
42168             setTimeout(function() {
 
42169                 reveal('.preset-search-input',
 
42170                     t('intro.points.search', {name: context.presets().item('amenity/cafe').name()}));
 
42171                 d3.select('.preset-search-input').on('keyup.intro', keySearch);
 
42175         function keySearch() {
 
42176             var first = d3.select('.preset-list-item:first-child');
 
42177             if (first.classed('preset-amenity-cafe')) {
 
42178                 reveal(first.select('.preset-list-button').node(), t('intro.points.choose'));
 
42179                 d3.selection.prototype.one.call(context.history(), 'change.intro', selectedPreset);
 
42180                 d3.select('.preset-search-input')
 
42181                     .on('keydown.intro', eventCancel, true)
 
42182                     .on('keyup.intro', null);
 
42186         function selectedPreset() {
 
42187             setTimeout(function() {
 
42188                 reveal('.entity-editor-pane', t('intro.points.describe'), {tooltipClass: 'intro-points-describe'});
 
42189                 context.history().on('change.intro', closeEditor);
 
42190                 context.on('exit.intro', selectPoint);
 
42194         function closeEditor() {
 
42195             d3.select('.preset-search-input').on('keydown.intro', null);
 
42196             context.history().on('change.intro', null);
 
42197             reveal('.entity-editor-pane',
 
42198                 t('intro.points.close', { button: iD.ui.intro.icon('#icon-apply', 'pre-text') }));
 
42201         function selectPoint() {
 
42202             context.on('exit.intro', null);
 
42203             context.history().on('change.intro', null);
 
42204             context.on('enter.intro', enterReselect);
 
42206             var pointBox = iD.ui.intro.pad(corner, 150, context);
 
42207             reveal(pointBox, t('intro.points.reselect'));
 
42209             context.map().on('move.intro', function() {
 
42210                 pointBox = iD.ui.intro.pad(corner, 150, context);
 
42211                 reveal(pointBox, t('intro.points.reselect'), {duration: 0});
 
42215         function enterReselect(mode) {
 
42216             if (mode.id !== 'select') return;
 
42217             context.map().on('move.intro', null);
 
42218             context.on('enter.intro', null);
 
42220             setTimeout(function() {
 
42221                 reveal('.entity-editor-pane',
 
42222                     t('intro.points.fixname', { button: iD.ui.intro.icon('#icon-apply', 'pre-text') }));
 
42223                 context.on('exit.intro', deletePoint);
 
42227         function deletePoint() {
 
42228             context.on('exit.intro', null);
 
42229             context.on('enter.intro', enterDelete);
 
42231             var pointBox = iD.ui.intro.pad(corner, 150, context);
 
42232             reveal(pointBox, t('intro.points.reselect_delete'));
 
42234             context.map().on('move.intro', function() {
 
42235                 pointBox = iD.ui.intro.pad(corner, 150, context);
 
42236                 reveal(pointBox, t('intro.points.reselect_delete'), {duration: 0});
 
42240         function enterDelete(mode) {
 
42241             if (mode.id !== 'select') return;
 
42242             context.map().on('move.intro', null);
 
42243             context.on('enter.intro', null);
 
42244             context.on('exit.intro', deletePoint);
 
42245             context.map().on('move.intro', deletePoint);
 
42246             context.history().on('change.intro', deleted);
 
42248             setTimeout(function() {
 
42249                 var node = d3.select('.radial-menu-item-delete').node();
 
42250                 var pointBox = iD.ui.intro.pad(node.getBoundingClientRect(), 50, context);
 
42252                     t('intro.points.delete', { button: iD.ui.intro.icon('#operation-delete', 'pre-text') }));
 
42256         function deleted(changed) {
 
42257             if (changed.deleted().length) event.done();
 
42262     step.exit = function() {
 
42263         timeouts.forEach(window.clearTimeout);
 
42264         context.on('exit.intro', null);
 
42265         context.on('enter.intro', null);
 
42266         context.map().on('move.intro', null);
 
42267         context.history().on('change.intro', null);
 
42268         d3.select('.preset-search-input')
 
42269             .on('keyup.intro', null)
 
42270             .on('keydown.intro', null);
 
42273     return d3.rebind(step, event, 'on');
 
42275 iD.ui.intro.startEditing = function(context, reveal) {
 
42276     var event = d3.dispatch('done', 'startEditing'),
 
42281         title: 'intro.startediting.title'
 
42284     function timeout(f, t) {
 
42285         timeouts.push(window.setTimeout(f, t));
 
42288     step.enter = function() {
 
42289         reveal('.map-control.help-control',
 
42290             t('intro.startediting.help', { button: iD.ui.intro.icon('#icon-help', 'pre-text') }));
 
42292         timeout(function() {
 
42293             reveal('#bar button.save', t('intro.startediting.save'));
 
42296         timeout(function() {
 
42297             reveal('#surface');
 
42300         timeout(function() {
 
42301             modal = iD.ui.modal(context.container());
 
42303             modal.select('.modal')
 
42304                 .attr('class', 'modal-splash modal col6');
 
42306             modal.selectAll('.close').remove();
 
42308             var startbutton = modal.select('.content')
 
42309                 .attr('class', 'fillL')
 
42311                         .attr('class', 'modal-section huge-modal-button')
 
42312                         .on('click', function() {
 
42316                 startbutton.append('div')
 
42317                     .attr('class','illustration');
 
42318                 startbutton.append('h2')
 
42319                     .text(t('intro.startediting.start'));
 
42321             event.startEditing();
 
42325     step.exit = function() {
 
42326         if (modal) modal.remove();
 
42327         timeouts.forEach(window.clearTimeout);
 
42330     return d3.rebind(step, event, 'on');
 
42332 iD.presets = function() {
 
42334     // an iD.presets.Collection with methods for
 
42335     // loading new data and returning defaults
 
42337     var all = iD.presets.Collection([]),
 
42338         defaults = { area: all, line: all, point: all, vertex: all, relation: all },
 
42341         recent = iD.presets.Collection([]);
 
42343     // Index of presets by (geometry, tag key).
 
42352     all.match = function(entity, resolver) {
 
42353         var geometry = entity.geometry(resolver);
 
42355         // Treat entities on addr:interpolation lines as points, not vertices (#3241)
 
42356         if (geometry === 'vertex' && entity.isOnAddressLine(resolver)) {
 
42357             geometry = 'point';
 
42360         var geometryMatches = index[geometry],
 
42364         for (var k in entity.tags) {
 
42365             var keyMatches = geometryMatches[k];
 
42366             if (!keyMatches) continue;
 
42368             for (var i = 0; i < keyMatches.length; i++) {
 
42369                 var score = keyMatches[i].matchScore(entity);
 
42370                 if (score > best) {
 
42372                     match = keyMatches[i];
 
42377         return match || all.item(geometry);
 
42380     // Because of the open nature of tagging, iD will never have a complete
 
42381     // list of tags used in OSM, so we want it to have logic like "assume
 
42382     // that a closed way with an amenity tag is an area, unless the amenity
 
42383     // is one of these specific types". This function computes a structure
 
42384     // that allows testing of such conditions, based on the presets designated
 
42385     // as as supporting (or not supporting) the area geometry.
 
42387     // The returned object L is a whitelist/blacklist of tags. A closed way
 
42388     // with a tag (k, v) is considered to be an area if `k in L && !(v in L[k])`
 
42389     // (see `iD.Way#isArea()`). In other words, the keys of L form the whitelist,
 
42390     // and the subkeys form the blacklist.
 
42391     all.areaKeys = function() {
 
42393             ignore = ['barrier', 'highway', 'footway', 'railway', 'type'],
 
42394             presets = _.reject(all.collection, 'suggestion');
 
42397         presets.forEach(function(d) {
 
42398             for (var key in d.tags) break;
 
42400             if (ignore.indexOf(key) !== -1) return;
 
42402             if (d.geometry.indexOf('area') !== -1) {
 
42403                 areaKeys[key] = areaKeys[key] || {};
 
42408         presets.forEach(function(d) {
 
42409             for (var key in d.tags) break;
 
42411             if (ignore.indexOf(key) !== -1) return;
 
42413             var value = d.tags[key];
 
42414             if (d.geometry.indexOf('area') === -1 &&
 
42415                 d.geometry.indexOf('line') !== -1 &&
 
42416                 key in areaKeys && value !== '*') {
 
42417                 areaKeys[key][value] = true;
 
42424     all.load = function(d) {
 
42427             _.forEach(d.fields, function(d, id) {
 
42428                 fields[id] = iD.presets.Field(id, d);
 
42429                 if (d.universal) universal.push(fields[id]);
 
42434             _.forEach(d.presets, function(d, id) {
 
42435                 all.collection.push(iD.presets.Preset(id, d, fields));
 
42439         if (d.categories) {
 
42440             _.forEach(d.categories, function(d, id) {
 
42441                 all.collection.push(iD.presets.Category(id, d, all));
 
42446             var getItem = _.bind(all.item, all);
 
42448                 area: iD.presets.Collection(d.defaults.area.map(getItem)),
 
42449                 line: iD.presets.Collection(d.defaults.line.map(getItem)),
 
42450                 point: iD.presets.Collection(d.defaults.point.map(getItem)),
 
42451                 vertex: iD.presets.Collection(d.defaults.vertex.map(getItem)),
 
42452                 relation: iD.presets.Collection(d.defaults.relation.map(getItem))
 
42456         for (var i = 0; i < all.collection.length; i++) {
 
42457             var preset = all.collection[i],
 
42458                 geometry = preset.geometry;
 
42460             for (var j = 0; j < geometry.length; j++) {
 
42461                 var g = index[geometry[j]];
 
42462                 for (var k in preset.tags) {
 
42463                     (g[k] = g[k] || []).push(preset);
 
42471     all.field = function(id) {
 
42475     all.universal = function() {
 
42479     all.defaults = function(geometry, n) {
 
42480         var rec = recent.matchGeometry(geometry).collection.slice(0, 4),
 
42481             def = _.uniq(rec.concat(defaults[geometry].collection)).slice(0, n - 1);
 
42482         return iD.presets.Collection(_.uniq(rec.concat(def).concat(all.item(geometry))));
 
42485     all.choose = function(preset) {
 
42486         if (!preset.isFallback()) {
 
42487             recent = iD.presets.Collection(_.uniq([preset].concat(recent.collection)));
 
42494 iD.presets.Category = function(id, category, all) {
 
42495     category = _.clone(category);
 
42499     category.members = iD.presets.Collection(category.members.map(function(id) {
 
42500         return all.item(id);
 
42503     category.matchGeometry = function(geometry) {
 
42504         return category.geometry.indexOf(geometry) >= 0;
 
42507     category.matchScore = function() { return -1; };
 
42509     category.name = function() {
 
42510         return t('presets.categories.' + id + '.name', {'default': id});
 
42513     category.terms = function() {
 
42519 iD.presets.Collection = function(collection) {
 
42521     var maxSearchResults = 50,
 
42522         maxSuggestionResults = 10;
 
42526         collection: collection,
 
42528         item: function(id) {
 
42529             return _.find(collection, function(d) {
 
42530                 return d.id === id;
 
42534         matchGeometry: function(geometry) {
 
42535             return iD.presets.Collection(collection.filter(function(d) {
 
42536                 return d.matchGeometry(geometry);
 
42540         search: function(value, geometry) {
 
42541             if (!value) return this;
 
42543             value = value.toLowerCase();
 
42545             var searchable = _.filter(collection, function(a) {
 
42546                     return a.searchable !== false && a.suggestion !== true;
 
42548                 suggestions = _.filter(collection, function(a) {
 
42549                     return a.suggestion === true;
 
42552             function leading(a) {
 
42553                 var index = a.indexOf(value);
 
42554                 return index === 0 || a[index - 1] === ' ';
 
42557             // matches value to preset.name
 
42558             var leading_name = _.filter(searchable, function(a) {
 
42559                     return leading(a.name().toLowerCase());
 
42560                 }).sort(function(a, b) {
 
42561                     var i = a.name().toLowerCase().indexOf(value) - b.name().toLowerCase().indexOf(value);
 
42562                     if (i === 0) return a.name().length - b.name().length;
 
42566             // matches value to preset.terms values
 
42567             var leading_terms = _.filter(searchable, function(a) {
 
42568                     return _.some(a.terms() || [], leading);
 
42571             // matches value to preset.tags values
 
42572             var leading_tag_values = _.filter(searchable, function(a) {
 
42573                     return _.some(_.without(_.values(a.tags || {}), '*'), leading);
 
42577             // finds close matches to value in preset.name
 
42578             var levenstein_name = searchable.map(function(a) {
 
42581                         dist: iD.util.editDistance(value, a.name().toLowerCase())
 
42583                 }).filter(function(a) {
 
42584                     return a.dist + Math.min(value.length - a.preset.name().length, 0) < 3;
 
42585                 }).sort(function(a, b) {
 
42586                     return a.dist - b.dist;
 
42587                 }).map(function(a) {
 
42591             // finds close matches to value in preset.terms
 
42592             var leventstein_terms = _.filter(searchable, function(a) {
 
42593                     return _.some(a.terms() || [], function(b) {
 
42594                         return iD.util.editDistance(value, b) + Math.min(value.length - b.length, 0) < 3;
 
42598             function suggestionName(name) {
 
42599                 var nameArray = name.split(' - ');
 
42600                 if (nameArray.length > 1) {
 
42601                     name = nameArray.slice(0, nameArray.length-1).join(' - ');
 
42603                 return name.toLowerCase();
 
42606             var leading_suggestions = _.filter(suggestions, function(a) {
 
42607                     return leading(suggestionName(a.name()));
 
42608                 }).sort(function(a, b) {
 
42609                     a = suggestionName(a.name());
 
42610                     b = suggestionName(b.name());
 
42611                     var i = a.indexOf(value) - b.indexOf(value);
 
42612                     if (i === 0) return a.length - b.length;
 
42616             var leven_suggestions = suggestions.map(function(a) {
 
42619                         dist: iD.util.editDistance(value, suggestionName(a.name()))
 
42621                 }).filter(function(a) {
 
42622                     return a.dist + Math.min(value.length - suggestionName(a.preset.name()).length, 0) < 1;
 
42623                 }).sort(function(a, b) {
 
42624                     return a.dist - b.dist;
 
42625                 }).map(function(a) {
 
42629             var other = presets.item(geometry);
 
42631             var results = leading_name.concat(
 
42633                             leading_tag_values,
 
42634                             leading_suggestions.slice(0, maxSuggestionResults+5),
 
42637                             leven_suggestions.slice(0, maxSuggestionResults)
 
42638                         ).slice(0, maxSearchResults-1);
 
42640             return iD.presets.Collection(_.uniq(
 
42641                     results.concat(other)
 
42648 iD.presets.Field = function(id, field) {
 
42649     field = _.clone(field);
 
42653     field.matchGeometry = function(geometry) {
 
42654         return !field.geometry || field.geometry === geometry;
 
42657     field.t = function(scope, options) {
 
42658         return t('presets.fields.' + id + '.' + scope, options);
 
42661     field.label = function() {
 
42662         return field.t('label', {'default': id});
 
42665     var placeholder = field.placeholder;
 
42666     field.placeholder = function() {
 
42667         return field.t('placeholder', {'default': placeholder});
 
42672 iD.presets.Preset = function(id, preset, fields) {
 
42673     preset = _.clone(preset);
 
42676     preset.fields = (preset.fields || []).map(getFields);
 
42677     preset.geometry = (preset.geometry || []);
 
42679     function getFields(f) {
 
42683     preset.matchGeometry = function(geometry) {
 
42684         return preset.geometry.indexOf(geometry) >= 0;
 
42687     var matchScore = preset.matchScore || 1;
 
42688     preset.matchScore = function(entity) {
 
42689         var tags = preset.tags,
 
42692         for (var t in tags) {
 
42693             if (entity.tags[t] === tags[t]) {
 
42694                 score += matchScore;
 
42695             } else if (tags[t] === '*' && t in entity.tags) {
 
42696                 score += matchScore / 2;
 
42705     preset.t = function(scope, options) {
 
42706         return t('presets.presets.' + id + '.' + scope, options);
 
42709     var name = preset.name;
 
42710     preset.name = function() {
 
42711         if (preset.suggestion) {
 
42712             id = id.split('/');
 
42713             id = id[0] + '/' + id[1];
 
42714             return name + ' - ' + t('presets.presets.' + id + '.name');
 
42716         return preset.t('name', {'default': name});
 
42719     preset.terms = function() {
 
42720         return preset.t('terms', {'default': ''}).toLowerCase().trim().split(/\s*,+\s*/);
 
42723     preset.isFallback = function() {
 
42724         var tagCount = Object.keys(preset.tags).length;
 
42725         return tagCount === 0 || (tagCount === 1 && preset.tags.hasOwnProperty('area'));
 
42728     preset.reference = function(geometry) {
 
42729         var key = Object.keys(preset.tags)[0],
 
42730             value = preset.tags[key];
 
42732         if (geometry === 'relation' && key === 'type') {
 
42733             return { rtype: value };
 
42734         } else if (value === '*') {
 
42735             return { key: key };
 
42737             return { key: key, value: value };
 
42741     var removeTags = preset.removeTags || preset.tags;
 
42742     preset.removeTags = function(tags, geometry) {
 
42743         tags = _.omit(tags, _.keys(removeTags));
 
42745         for (var f in preset.fields) {
 
42746             var field = preset.fields[f];
 
42747             if (field.matchGeometry(geometry) && field.default === tags[field.key]) {
 
42748                 delete tags[field.key];
 
42756     var applyTags = preset.addTags || preset.tags;
 
42757     preset.applyTags = function(tags, geometry) {
 
42760         tags = _.clone(tags);
 
42762         for (k in applyTags) {
 
42763             if (applyTags[k] === '*') {
 
42766                 tags[k] = applyTags[k];
 
42770         // Add area=yes if necessary.
 
42771         // This is necessary if the geometry is already an area (e.g. user drew an area) AND any of:
 
42772         // 1. chosen preset could be either an area or a line (`barrier=city_wall`)
 
42773         // 2. chosen preset doesn't have a key in areaKeys (`railway=station`)
 
42774         if (geometry === 'area') {
 
42775             var needsAreaTag = true;
 
42776             if (preset.geometry.indexOf('line') === -1) {
 
42777                 for (k in applyTags) {
 
42778                     if (k in iD.areaKeys) {
 
42779                         needsAreaTag = false;
 
42784             if (needsAreaTag) {
 
42789         for (var f in preset.fields) {
 
42790             var field = preset.fields[f];
 
42791             if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field.default) {
 
42792                 tags[field.key] = field.default;
 
42801 iD.validations = {};
 
42802 iD.validations.DeprecatedTag = function() {
 
42804     var validation = function(changes) {
 
42806         for (var i = 0; i < changes.created.length; i++) {
 
42807             var change = changes.created[i],
 
42808                 deprecatedTags = change.deprecatedTags();
 
42810             if (!_.isEmpty(deprecatedTags)) {
 
42811                 var tags = iD.util.tagText({ tags: deprecatedTags });
 
42813                     id: 'deprecated_tags',
 
42814                     message: t('validations.deprecated_tags', { tags: tags }),
 
42824 iD.validations.ManyDeletions = function() {
 
42825     var threshold = 100;
 
42827     var validation = function(changes) {
 
42829         if (changes.deleted.length > threshold) {
 
42831                 id: 'many_deletions',
 
42832                 message: t('validations.many_deletions', { n: changes.deleted.length })
 
42840 iD.validations.MissingTag = function() {
 
42842     // Slightly stricter check than Entity#isUsed (#3091)
 
42843     function hasTags(entity, graph) {
 
42844         return _.without(Object.keys(entity.tags), 'area', 'name').length > 0 ||
 
42845             graph.parentRelations(entity).length > 0;
 
42848     var validation = function(changes, graph) {
 
42850         for (var i = 0; i < changes.created.length; i++) {
 
42851             var change = changes.created[i],
 
42852                 geometry = change.geometry(graph);
 
42854             if ((geometry === 'point' || geometry === 'line' || geometry === 'area') && !hasTags(change, graph)) {
 
42857                     message: t('validations.untagged_' + geometry),
 
42858                     tooltip: t('validations.untagged_' + geometry + '_tooltip'),
 
42868 iD.validations.TagSuggestsArea = function() {
 
42870     // https://github.com/openstreetmap/josm/blob/mirror/src/org/
 
42871     // openstreetmap/josm/data/validation/tests/UnclosedWays.java#L80
 
42872     function tagSuggestsArea(tags) {
 
42873         if (_.isEmpty(tags)) return false;
 
42875         var presence = ['landuse', 'amenities', 'tourism', 'shop'];
 
42876         for (var i = 0; i < presence.length; i++) {
 
42877             if (tags[presence[i]] !== undefined) {
 
42878                 return presence[i] + '=' + tags[presence[i]];
 
42882         if (tags.building && tags.building === 'yes') return 'building=yes';
 
42885     var validation = function(changes, graph) {
 
42887         for (var i = 0; i < changes.created.length; i++) {
 
42888             var change = changes.created[i],
 
42889                 geometry = change.geometry(graph),
 
42890                 suggestion = (geometry === 'line' ? tagSuggestsArea(change.tags) : undefined);
 
42894                     id: 'tag_suggests_area',
 
42895                     message: t('validations.tag_suggests_area', { tag: suggestion }),
 
42906 window.locale = { _current: 'en' };
 
42908 locale.current = function(_) {
 
42909     if (!arguments.length) return locale._current;
 
42910     if (locale[_] !== undefined) locale._current = _;
 
42911     else if (locale[_.split('-')[0]]) locale._current = _.split('-')[0];
 
42915 function t(s, o, loc) {
 
42916     loc = loc || locale._current;
 
42918     var path = s.split(".").reverse(),
 
42921     while (rep !== undefined && path.length) rep = rep[path.pop()];
 
42923     if (rep !== undefined) {
 
42924         if (o) for (var k in o) rep = rep.replace('{' + k + '}', o[k]);
 
42928     if (loc !== 'en') {
 
42929         return t(s, o, 'en');
 
42932     if (o && 'default' in o) {
 
42933         return o['default'];
 
42936     var missing = 'Missing ' + loc + ' translation: ' + s;
 
42937     if (typeof console !== "undefined") console.error(missing);
 
42941 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"],["Adyghe","адыгабзэ","ady"],["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"],["تۆرکجه","تۆرکجه","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","गोंयची कोंकणी / Gõychi 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 Creole","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"],["Jamaican Creole English","Patois","jam"],["Lojban","la .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","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":{},"geometry":{"type":"Polygon","coordinates":[[[1.97754,51.13111],[1.8457,63.45051],[-10.45898,57.01681],[-6.82251,55.26503],[-7.25583,55.06525],[-7.26546,55.0665],[-7.26992,55.06419],[-7.2725,55.06346],[-7.27818,55.05362],[-7.2893,55.04735],[-7.29939,55.0561],[-7.31835,55.04475],[-7.3447,55.05079],[-7.38831,55.02389],[-7.40547,55.00292],[-7.39157,54.99507],[-7.40075,54.98892],[-7.40706,54.98291],[-7.40363,54.97963],[-7.40633,54.97813],[-7.39835,54.97013],[-7.40745,54.96357],[-7.40178,54.95961],[-7.40727,54.95515],[-7.3944,54.94376],[-7.44444,54.93858],[-7.45216,54.89793],[-7.44204,54.87532],[-7.4713,54.83431],[-7.48092,54.83093],[-7.49216,54.82185],[-7.55121,54.79054],[-7.5443,54.78609],[-7.54958,54.75653],[-7.5349,54.74917],[-7.54881,54.74068],[-7.55941,54.74556],[-7.57894,54.74221],[-7.57507,54.7494],[-7.58606,54.75039],[-7.58872,54.74377],[-7.60031,54.74603],[-7.60632,54.74405],[-7.61662,54.74459],[-7.63593,54.75108],[-7.68854,54.72968],[-7.72064,54.72155],[-7.75094,54.70469],[-7.79094,54.71942],[-7.8051,54.71932],[-7.83497,54.73632],[-7.85419,54.72745],[-7.91496,54.67582],[-7.90174,54.66182],[-7.83832,54.63401],[-7.7433,54.6188],[-7.70863,54.63485],[-7.70682,54.6189],[-7.69386,54.6188],[-7.69631,54.61125],[-7.75845,54.59509],[-7.78708,54.58],[-7.79446,54.58141],[-7.79969,54.57704],[-7.79673,54.56915],[-7.8184,54.56315],[-7.83334,54.55227],[-7.82737,54.54299],[-7.85007,54.53363],[-7.90741,54.53722],[-7.93213,54.53388],[-8.00487,54.54568],[-8.03727,54.51162],[-8.04285,54.48759],[-8.08027,54.48829],[-8.09988,54.48395],[-8.09126,54.4765],[-8.111,54.47807],[-8.11512,54.46904],[-8.16542,54.46914],[-8.1776,54.46485],[-8.14293,54.45003],[-8.16284,54.4413],[-8.08731,54.4002],[-8.06062,54.37051],[-8.03289,54.35711],[-8.00054,54.34835],[-7.93333,54.30561],[-7.85849,54.29151],[-7.87067,54.28794],[-7.87265,54.26648],[-7.86123,54.25931],[-7.85917,54.21256],[-7.71043,54.20307],[-7.70193,54.20776],[-7.68828,54.202],[-7.67644,54.18906],[-7.66082,54.1871],[-7.62554,54.16545],[-7.62541,54.15319],[-7.61026,54.14353],[-7.57421,54.14142],[-7.57181,54.13287],[-7.56228,54.12704],[-7.51379,54.12998],[-7.47944,54.122],[-7.47169,54.12665],[-7.47075,54.13318],[-7.44684,54.15168],[-7.40792,54.156],[-7.42579,54.14092],[-7.41903,54.13629],[-7.3744,54.14172],[-7.37234,54.13881],[-7.39509,54.12624],[-7.39182,54.12017],[-7.36341,54.13157],[-7.34518,54.11577],[-7.32471,54.12123],[-7.32003,54.11379],[-7.3078,54.11718],[-7.30548,54.12347],[-7.31591,54.12697],[-7.31213,54.13162],[-7.3187,54.13411],[-7.31857,54.13745],[-7.32222,54.13836],[-7.32737,54.13544],[-7.3399,54.14585],[-7.30827,54.16716],[-7.30024,54.16625],[-7.29029,54.1715],[-7.28158,54.16839],[-7.2863,54.14919],[-7.29874,54.14904],[-7.30162,54.14411],[-7.28411,54.13971],[-7.29192,54.13071],[-7.29737,54.133],[-7.30883,54.13242],[-7.30333,54.12251],[-7.29218,54.11929],[-7.27844,54.12282],[-7.27707,54.12986],[-7.26613,54.13624],[-7.2566,54.16354],[-7.24015,54.17125],[-7.2575,54.17678],[-7.2581,54.19257],[-7.25179,54.19403],[-7.23608,54.1935],[-7.23338,54.19792],[-7.24317,54.20076],[-7.24892,54.1977],[-7.25183,54.20201],[-7.24119,54.20623],[-7.23094,54.20578],[-7.23269,54.20912],[-7.22188,54.21607],[-7.20643,54.2117],[-7.18506,54.22485],[-7.17055,54.21742],[-7.14721,54.22488],[-7.14633,54.23008],[-7.15051,54.23165],[-7.14613,54.23983],[-7.15802,54.24434],[-7.13985,54.25298],[-7.15255,54.26235],[-7.16064,54.27405],[-7.17991,54.27144],[-7.17201,54.28627],[-7.21252,54.2985],[-7.19888,54.31117],[-7.17918,54.30946],[-7.1812,54.3397],[-7.15339,54.33514],[-7.10253,54.35811],[-7.10811,54.36677],[-7.06927,54.3899],[-7.05593,54.41056],[-7.02898,54.42135],[-7.00198,54.40832],[-6.98683,54.40829],[-6.97562,54.40014],[-6.96774,54.40145],[-6.90682,54.36966],[-6.89772,54.35075],[-6.87527,54.33853],[-6.86512,54.32568],[-6.85163,54.29137],[-6.87452,54.28677],[-6.87791,54.27918],[-6.86673,54.27522],[-6.85177,54.26489],[-6.83693,54.26658],[-6.82165,54.24346],[-6.81633,54.22299],[-6.80045,54.22108],[-6.80122,54.21338],[-6.77599,54.19965],[-6.75573,54.1987],[-6.74316,54.18258],[-6.73406,54.18566],[-6.72445,54.18127],[-6.70295,54.20036],[-6.69166,54.20018],[-6.68673,54.19398],[-6.669,54.19584],[-6.65248,54.18102],[-6.6433,54.17801],[-6.63467,54.16449],[-6.63179,54.14766],[-6.64081,54.14238],[-6.63935,54.13599],[-6.66149,54.1205],[-6.6481,54.10153],[-6.66119,54.0934],[-6.66458,54.06629],[-6.64681,54.05873],[-6.62501,54.03737],[-6.59291,54.04755],[-6.58905,54.05808],[-6.5597,54.0481],[-6.52897,54.05888],[-6.50442,54.05566],[-6.47824,54.07004],[-6.47919,54.07762],[-6.43601,54.05959],[-6.36314,54.07057],[-6.36589,54.09338],[-6.36293,54.09758],[-6.37104,54.11497],[-6.3522,54.11084],[-6.34242,54.1114],[-6.33589,54.10833],[-6.33636,54.09469],[-6.31808,54.09096],[-6.30903,54.10463],[-6.29165,54.11235],[-6.28246,54.11145],[-6.26272,54.09786],[-5.35583,53.72597],[-7.0752,49.23912],[-1.83472,49.02346],[-2.12036,49.94415],[1.97754,51.13111]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-65.2,18.7],[-65,16.3],[-63.7,19.2],[-65.2,18.7]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-63,-50.5],[-55,-51],[-60,-54],[-63,-50.5]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-139.19952,60.08402],[-141,60.30621],[-141,76],[-169,68.63655],[-169,65.20147],[-180,61],[-180,-4],[-154,9],[-133.76404,54.54021],[-130.73868,54.71986],[-129.96277,55.29163],[-130.15228,55.7758],[-130.01787,55.90688],[-130.00362,56.00798],[-130.10284,56.12336],[-130.24498,56.09656],[-130.42625,56.14249],[-131.87439,56.79787],[-135.02884,59.56285],[-135.11759,59.62306],[-135.15827,59.6261],[-135.47928,59.79822],[-136.28677,59.57955],[-136.30531,59.46462],[-136.36836,59.44898],[-136.47697,59.46558],[-137.19727,59.01935],[-139.19952,60.08402]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-111.96064,48.99841],[-121.22623,49.00049],[-122.26513,49.00246],[-122.7565,49.00208],[-123.32218,49.00218],[-122.97821,48.76524],[-123.2666,48.69821],[-123.21991,48.21186],[-125.80444,48.60749],[-124.32129,31.54109],[-117.125,32.53429],[-116.82417,32.55996],[-115.88036,32.63735],[-115.49738,32.66486],[-114.71984,32.71877],[-114.7649,32.64602],[-114.80885,32.60959],[-114.81481,32.49451],[-112.81743,31.88004],[-111.07481,31.33224],[-109.56051,31.33402],[-108.20847,31.33384],[-108.20838,31.78363],[-106.52847,31.78391],[-106.52781,31.78086],[-106.52249,31.77501],[-106.51249,31.76933],[-106.50988,31.7612],[-106.50709,31.76123],[-106.48896,31.74806],[-106.48473,31.74769],[-106.4719,31.75101],[-106.46816,31.75897],[-106.45434,31.76466],[-106.45035,31.76426],[-106.43516,31.75492],[-106.41484,31.75101],[-106.37864,31.73021],[-106.37225,31.71174],[-106.34924,31.69633],[-106.33289,31.66178],[-106.3068,31.62459],[-106.28079,31.56179],[-106.24775,31.54226],[-106.2329,31.49982],[-106.2105,31.46857],[-106.08201,31.39863],[-106.00554,31.39233],[-105.76401,31.17051],[-105.58548,31.06117],[-105.56419,30.98526],[-104.99153,30.6639],[-104.97162,30.60896],[-104.90639,30.57822],[-104.83772,30.38117],[-104.70177,30.20567],[-104.68048,29.92399],[-104.57611,29.77838],[-104.51157,29.63674],[-104.39758,29.57047],[-104.39278,29.55293],[-104.05769,29.32173],[-103.79883,29.2581],[-103.78196,29.26555],[-103.76759,29.22799],[-103.14102,28.93666],[-102.86087,29.2217],[-102.65076,29.79418],[-101.41068,29.73457],[-101.26511,29.51372],[-101.05997,29.452],[-101.04083,29.38038],[-100.96303,29.34735],[-100.94406,29.34369],[-100.94071,29.33351],[-100.92775,29.32663],[-100.89814,29.30957],[-100.87818,29.28086],[-100.80076,29.2238],[-100.76437,29.15981],[-100.67047,29.08663],[-100.6412,28.91299],[-100.63236,28.90255],[-100.61296,28.89939],[-100.534,28.75622],[-100.51495,28.74531],[-100.50705,28.7143],[-100.51203,28.70666],[-100.51014,28.69127],[-100.50048,28.66186],[-100.45547,28.6381],[-100.44697,28.60743],[-100.35599,28.45239],[-100.34946,28.39653],[-100.29488,28.31315],[-100.29591,28.27324],[-100.17197,28.17493],[-99.93645,27.9568],[-99.87722,27.80173],[-99.79671,27.73338],[-99.772,27.72532],[-99.74556,27.69979],[-99.71947,27.65981],[-99.5957,27.59974],[-99.54094,27.60537],[-99.53055,27.57973],[-99.52034,27.55782],[-99.52802,27.49773],[-99.50141,27.49986],[-99.48755,27.49518],[-99.47897,27.48421],[-99.48661,27.46453],[-99.49534,27.44861],[-99.48927,27.40941],[-99.53957,27.31565],[-99.43588,27.19678],[-99.46404,27.01968],[-99.16698,26.56039],[-99.17474,26.53939],[-99.12698,26.51958],[-99.1135,26.42954],[-99.08355,26.39625],[-99.06007,26.39737],[-99.03634,26.41255],[-99.02042,26.40598],[-99.01291,26.39364],[-98.95686,26.38641],[-98.9566,26.37365],[-98.94523,26.36949],[-98.90013,26.36419],[-98.89905,26.35454],[-98.80305,26.36626],[-98.78254,26.30511],[-98.66667,26.23457],[-98.58496,26.24647],[-98.57951,26.23434],[-98.56519,26.23987],[-98.56294,26.22464],[-98.50599,26.20858],[-98.44806,26.21236],[-98.38617,26.15721],[-98.34176,26.15278],[-98.33579,26.1388],[-98.30626,26.10003],[-98.28841,26.10512],[-98.26524,26.0914],[-98.19898,26.06411],[-98.09577,26.05698],[-98.07568,26.06667],[-98.08302,26.03396],[-97.9771,26.04136],[-97.9532,26.06179],[-97.81643,26.04475],[-97.77017,26.02439],[-97.73884,26.02902],[-97.5289,25.90648],[-97.52151,25.88625],[-97.50615,25.89031],[-97.49851,25.89903],[-97.49637,25.89641],[-97.49748,25.88008],[-97.49422,25.87981],[-97.48847,25.88564],[-97.46409,25.88174],[-97.42607,25.842],[-97.36856,25.8396],[-97.26231,25.94724],[-80.81543,24.00633],[-66.87378,44.77794],[-67.16148,45.16715],[-67.2286,45.16739],[-67.26246,45.18797],[-67.28311,45.19175],[-67.28959,45.18784],[-67.29332,45.17568],[-67.29049,45.17317],[-67.3001,45.16776],[-67.3025,45.16122],[-67.29761,45.14766],[-67.33975,45.1255],[-67.40524,45.16122],[-67.40387,45.17139],[-67.4818,45.27682],[-67.42172,45.38543],[-67.45262,45.41008],[-67.50498,45.4889],[-67.41623,45.50105],[-67.42219,45.55661],[-67.42902,45.56833],[-67.42331,45.57154],[-67.42498,45.57836],[-67.45193,45.60323],[-67.77981,45.6738],[-67.79019,47.06776],[-67.88006,47.1067],[-67.91319,47.14793],[-67.92598,47.15418],[-67.95181,47.1875],[-68.02374,47.23915],[-68.13017,47.29309],[-68.17669,47.32893],[-68.24046,47.35354],[-68.32809,47.36005],[-68.36363,47.35476],[-68.38054,47.34167],[-68.38509,47.30321],[-68.37367,47.28796],[-68.4377,47.28232],[-68.47916,47.29623],[-68.51074,47.29885],[-68.54593,47.28441],[-68.58408,47.28482],[-68.59777,47.27134],[-68.59271,47.25762],[-68.61889,47.24148],[-68.68936,47.24125],[-68.71768,47.23676],[-68.80128,47.21423],[-68.89629,47.17676],[-69.05354,47.24847],[-69.04924,47.41798],[-69.22425,47.45961],[-69.99729,46.69558],[-70.0569,46.4149],[-70.25551,46.10871],[-70.29001,46.09431],[-70.39919,45.80667],[-70.83229,45.40062],[-70.80794,45.37878],[-70.82663,45.2367],[-70.87538,45.23453],[-70.92138,45.28099],[-70.90645,45.30918],[-71.0109,45.34798],[-71.08429,45.30556],[-71.1454,45.24226],[-71.20525,45.25278],[-71.28925,45.30097],[-71.41405,45.23513],[-71.43044,45.12381],[-71.49692,45.06991],[-71.50623,45.04878],[-71.49284,45.03629],[-71.50027,45.01372],[-71.79359,45.01075],[-72.08774,45.00581],[-72.14155,45.00568],[-72.15282,45.00609],[-72.17142,45.00584],[-72.25847,45.00436],[-72.38795,45.00626],[-72.4496,45.00863],[-72.5356,45.00936],[-72.66257,45.01523],[-72.82537,45.01642],[-73.08466,45.01561],[-73.45219,45.00875],[-74.14699,44.99145],[-74.33753,44.9923],[-74.50786,44.99798],[-74.66158,44.99949],[-74.71244,44.99734],[-74.75887,44.98708],[-74.76368,45.00632],[-74.78977,45.00365],[-74.82376,45.01773],[-74.94186,44.98229],[-75.30098,44.83883],[-75.30304,44.82836],[-75.59418,44.6457],[-75.97269,44.33502],[-75.97295,44.34595],[-76.00059,44.34797],[-76.17645,44.2865],[-76.18744,44.22158],[-76.88782,43.82759],[-79.16851,43.32168],[-79.05487,43.25371],[-79.05092,43.169],[-79.04603,43.16093],[-79.04208,43.13942],[-79.07002,43.12038],[-79.06015,43.114],[-79.0568,43.10474],[-79.0774,43.07861],[-78.9996,43.05484],[-79.02311,43.02071],[-79.02552,42.99473],[-78.96235,42.9573],[-78.91188,42.9426],[-78.90398,42.89181],[-82.42767,41.47978],[-83.14316,42.03807],[-83.12805,42.23843],[-83.09715,42.29052],[-83.07252,42.31515],[-82.94575,42.34332],[-82.59676,42.5479],[-82.51368,42.61785],[-82.5108,42.66464],[-82.4675,42.76415],[-82.48055,42.80573],[-82.45497,42.9284],[-82.41334,42.97099],[-82.42596,42.99536],[-82.15851,43.39507],[-83.53729,46.098],[-83.96301,46.05036],[-84.11021,46.23851],[-84.09794,46.25656],[-84.11613,46.26878],[-84.11905,46.31516],[-84.10721,46.3218],[-84.14394,46.41076],[-84.11682,46.51576],[-84.13536,46.53218],[-84.16162,46.5284],[-84.21621,46.53891],[-84.26994,46.49189],[-84.36092,46.50997],[-84.55284,46.4407],[-84.95178,46.77185],[-89.59179,48.00307],[-89.67547,48.00371],[-90.87204,48.25943],[-91.41312,48.06753],[-92.99377,48.62474],[-93.34877,48.62604],[-93.35529,48.61124],[-93.37074,48.60584],[-93.39812,48.60369],[-93.40542,48.61089],[-93.43846,48.59478],[-93.46859,48.59205],[-93.45735,48.56667],[-93.46533,48.54593],[-93.64763,48.51751],[-93.80625,48.51888],[-93.80642,48.58047],[-93.83328,48.62582],[-93.84865,48.63064],[-93.93388,48.6326],[-94.01327,48.64471],[-94.16176,48.64697],[-94.25025,48.65463],[-94.24931,48.67827],[-94.26046,48.69816],[-94.30578,48.71073],[-94.32758,48.70433],[-94.36123,48.70478],[-94.38406,48.71135],[-94.41629,48.71067],[-94.44294,48.69266],[-94.53615,48.7024],[-94.55031,48.71419],[-94.58894,48.71928],[-94.69425,48.77938],[-94.70129,48.83376],[-94.68996,48.83953],[-94.68395,48.99914],[-111.96064,48.99841]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[180,55],[170,53],[180,49],[180,55]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[143,22],[147,22],[147,12],[143,12],[143,22]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-171.5,-10],[-171,-15],[-167,-15],[-171.5,-10]]]}}]},"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","gu","hi","hu","is","id","it","ja","kn","ko","lv","lij","lt","ml","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 (required)","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","google_warning":"You mentioned Google in this comment: remember that copying from Google Maps is strictly forbidden.","google_warning_link":"http://www.openstreetmap.org/copyright"},"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","locating":"Locating, please wait..."},"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"},"add":"Add","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","switch":"Switch back to this background","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":"Adjust imagery offset","imagery_source_faq":"Where does this imagery come from?","reset":"reset","offset":"Drag anywhere in the gray area below to adjust the imagery offset, or enter the offset values in meters.","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"},"traffic_roads":{"description":"Traffic Roads","tooltip":"Highways, Streets, etc."},"service_roads":{"description":"Service 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 (must enable Photo Overlay)","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-barrier":{"name":"Barrier Features"},"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"},"bin":{"label":"Waste Bin"},"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"},"currency_multi":{"label":"Currency Types"},"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_multi":{"label":"Fuel Types"},"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"}},"internet_access/fee":{"label":"Internet Access Fee"},"kerb":{"label":"Curb Ramp"},"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..."},"parallel_direction":{"label":"Direction","options":{"forward":"Forward","backward":"Backward"}},"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"}},"payment_multi":{"label":"Payment Types"},"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_accepts":{"label":"Accepts"},"ref":{"label":"Reference"},"relation":{"label":"Type"},"religion":{"label":"Religion"},"restriction":{"label":"Type"},"restrictions":{"label":"Turn Restrictions"},"rooms":{"label":"Rooms"},"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"},"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"},"stars":{"label":"Stars"},"stop":{"label":"Stop Type","options":{"all":"All Ways","minor":"Minor Road"}},"structure":{"label":"Structure","placeholder":"Unknown","options":{"bridge":"Bridge","tunnel":"Tunnel","embankment":"Embankment","cutting":"Cutting","ford":"Ford"}},"studio":{"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,grill"},"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*,med*,prescription"},"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/prison":{"name":"Prison Grounds","terms":"cell,jail"},"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":"Trench","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/defibrillator":{"name":"Defibrillator","terms":""},"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/give_way":{"name":"Yield Sign","terms":"give way,yield,sign"},"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,halt,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/Unclassified 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/bird_hide":{"name":"Bird Hide","terms":"machan,ornithology"},"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/bridge":{"name":"Bridge","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":"dock"},"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":"Drugstore","terms":"med*,drug*,gift"},"shop/chocolate":{"name":"Chocolate Store","terms":""},"shop/clothes":{"name":"Clothing Store","terms":""},"shop/coffee":{"name":"Coffee 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/nutrition_supplements":{"name":"Nutrition Supplements Store","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/horse":{"name":"Riding 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":"Wet Dock / Dry Dock","terms":"boat,ship,vessel,marine"},"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":{"pub":{"The Green Man":{"count":54},"Kings Arms":{"count":77},"The White Horse":{"count":223},"The White Hart":{"count":238},"Royal Oak":{"count":175},"The Red Lion":{"count":253},"The Kings Arms":{"count":60},"The Star":{"count":74},"The Cross Keys":{"count":58},"The Wheatsheaf":{"count":121},"The Kings Head":{"count":63},"The Castle":{"count":63},"The Railway":{"count":105},"The Bell":{"count":129},"The Bull":{"count":75},"The Plough":{"count":187},"The George":{"count":115},"The Royal Oak":{"count":216},"The Fox":{"count":78},"Prince of Wales":{"count":86},"The Rising Sun":{"count":78},"The Chequers":{"count":72},"The Crown":{"count":253},"The Swan":{"count":149},"The Crown Inn":{"count":76},"The Ship":{"count":90},"The Victoria":{"count":69},"New Inn":{"count":104},"The Anchor":{"count":67},"Royal Hotel":{"count":62},"Red Lion":{"count":207},"Cross Keys":{"count":63},"The Bell Inn":{"count":57},"The White Lion":{"count":73},"The Black Horse":{"count":97},"Rose and Crown":{"count":85},"Commercial Hotel":{"count":54},"The White Swan":{"count":53},"The Greyhound":{"count":98},"The New Inn":{"count":119},"Kings Head":{"count":62},"The Angel":{"count":57},"The Queens Head":{"count":55},"Black Bull":{"count":54},"Black Horse":{"count":52},"The Swan Inn":{"count":54},"Rose & Crown":{"count":58},"The Albion":{"count":54},"The Cricketers":{"count":55},"The Ship Inn":{"count":94},"The Star Inn":{"count":51},"Queens Head":{"count":56},"Irish Pub":{"count":99},"魚民":{"count":84}},"fuel":{"76":{"count":498},"Neste":{"count":177},"Shell":{"count":10789},"Agip":{"count":2524},"Migrol":{"count":78},"Avia":{"count":1014},"Texaco":{"count":1057},"Total":{"count":3182},"Statoil":{"count":668},"BP":{"count":3517},"Topaz":{"count":98},"Esso":{"count":4179},"Jet":{"count":461},"OMV":{"count":929},"Aral":{"count":1383},"Tesco":{"count":214},"JET":{"count":212},"Morrisons":{"count":122},"United":{"count":155},"Sainsbury's":{"count":72},"Canadian Tire":{"count":90},"Mobil":{"count":1150},"Q8":{"count":1325},"Caltex":{"count":1304},"Petro-Canada":{"count":736},"ABC":{"count":84},"ARAL":{"count":385},"CEPSA":{"count":972},"BFT":{"count":102},"Petron":{"count":1283},"Intermarché":{"count":591},"Total Access":{"count":173},"Auchan":{"count":71},"Super U":{"count":147},"Carrefour":{"count":291},"Station Service E. Leclerc":{"count":516},"Elan":{"count":174},"Shell Express":{"count":171},"Hess":{"count":213},"F24":{"count":56},"Gulf":{"count":330},"PTT":{"count":241},"Teboil":{"count":111},"St1":{"count":126},"HEM":{"count":241},"GALP":{"count":762},"پمپ بنزین":{"count":266},"Avanti":{"count":110},"Cepsa":{"count":208},"OK":{"count":205},"Tinq":{"count":215},"Repsol":{"count":775},"Westfalen":{"count":94},"Esso Express":{"count":150},"Slovnaft":{"count":261},"Raiffeisenbank":{"count":129},"Tamoil":{"count":913},"bft":{"count":185},"Afriquia":{"count":117},"Engen":{"count":307},"Sasol":{"count":74},"Jetti":{"count":59},"LPG":{"count":309},"Coop":{"count":67},"Orlen":{"count":1074},"Kobil":{"count":81},"Oilibya":{"count":87},"Tango":{"count":143},"Star":{"count":352},"Петрол":{"count":111},"EKO":{"count":110},"Turmöl":{"count":74},"OIL!":{"count":111},"Flying V":{"count":146},"Ultramar":{"count":246},"CARREFOUR":{"count":73},"Eni":{"count":469},"Irving":{"count":149},"Lukoil":{"count":832},"Coles Express":{"count":262},"Pioneer":{"count":93},"Speedway":{"count":381},"Uno-X":{"count":57},"7-Eleven":{"count":892},"Agrola":{"count":90},"Husky":{"count":188},"Sunoco":{"count":684},"Sheetz":{"count":248},"Turkey Hill":{"count":56},"MOL":{"count":380},"OKQ8":{"count":209},"Petronas":{"count":254},"Mol":{"count":60},"Benzina":{"count":148},"Газпромнефть":{"count":1093},"Роснефть":{"count":805},"Opet":{"count":105},"Marathon":{"count":513},"Vito":{"count":63},"Valero":{"count":656},"Neste A24":{"count":56},"REPSOL":{"count":1502},"Lotos":{"count":260},"Api":{"count":253},"Chevron":{"count":1505},"ARCO":{"count":128},"Pemex":{"count":1340},"ТНК":{"count":594},"Petrol Ofisi":{"count":115},"eni":{"count":84},"Petrom":{"count":330},"PETRONOR":{"count":196},"Rompetrol":{"count":193},"Copec":{"count":541},"Petrobras":{"count":341},"АЗС":{"count":1060},"Pilot":{"count":57},"LUKOIL":{"count":64},"SB Tank":{"count":56},"Arco":{"count":391},"Лукойл":{"count":2285},"ОМВ":{"count":58},"Liberty":{"count":79},"Bliska":{"count":162},"Moya":{"count":52},"Erg":{"count":510},"Eneos":{"count":121},"P T T":{"count":55},"Citgo":{"count":547},"IP":{"count":967},"Metano":{"count":248},"Сургутнефтегаз":{"count":75},"ENI":{"count":79},"Eko":{"count":75},"Indipend.":{"count":144},"TotalErg":{"count":188},"IES":{"count":63},"Star Oil":{"count":77},"ERG":{"count":78},"Cenex":{"count":194},"ПТК":{"count":97},"Белоруснефть":{"count":64},"HP":{"count":127},"Phillips 66":{"count":332},"Q1":{"count":53},"ป.ต.ท.":{"count":449},"Circle K":{"count":313},"Woolworths Petrol":{"count":151},"PSO":{"count":80},"Татнефть":{"count":311},"Ceypetco":{"count":63},"Seaoil":{"count":55},"Sea Oil":{"count":65},"Phoenix":{"count":182},"Cosmo":{"count":61},"Gazprom":{"count":69},"Kwik Trip":{"count":169},"КазМунайГаз":{"count":163},"Wawa":{"count":143},"Pertamina":{"count":274},"เอสโซ่":{"count":85},"Terpel":{"count":337},"Z":{"count":93},"Socar":{"count":71},"Bharat Petroleum":{"count":166},"Indian Oil":{"count":327},"АГЗС":{"count":897},"JOMO":{"count":56},"Holiday":{"count":140},"ОККО":{"count":294},"Exxon":{"count":883},"コスモ石油":{"count":325},"出光":{"count":478,"tags":{"name:en":"IDEMITSU"}},"ENEOS":{"count":1292},"WOG":{"count":323},"CAMPSA":{"count":507},"Casey's General Store":{"count":307},"Башнефть":{"count":137},"Kangaroo":{"count":113},"Puma":{"count":315},"Hindustan Petroleum":{"count":58},"Lotos Optima":{"count":64},"MEROIL":{"count":74},"TEXACO":{"count":54},"ゼネラル":{"count":58},"Helios":{"count":61},"Татнефтепродукт":{"count":69},"昭和シェル":{"count":215},"BEBECO":{"count":77},"НК Альянс":{"count":97},"คาลเท็กซ์":{"count":72},"JA-SS":{"count":52},"Sinclair":{"count":163},"Costco":{"count":73},"Conoco":{"count":327},"SPBU":{"count":205},"Макпетрол":{"count":109},"Sam's Club":{"count":51},"Ipiranga":{"count":159},"1-2-3":{"count":68},"Posto Ipiranga":{"count":168},"Drummed Fuel":{"count":156},"Rubis":{"count":107},"БРСМ-Нафта":{"count":58},"АГНКС":{"count":54},"QuikTrip":{"count":209},"เชลล์":{"count":94},"Stewart's":{"count":66},"Cumberland Farms":{"count":80},"Posto BR":{"count":191},"台灣中油":{"count":147},"บางจาก":{"count":195},"محطه وقود":{"count":59},"ANP":{"count":163},"Kum & Go":{"count":113},"Primax":{"count":147},"Mobile":{"count":56},"Укрнафта":{"count":201},"Пропан":{"count":57},"Petrolimex":{"count":143},"Tela":{"count":171},"Авіас":{"count":97},"Sokimex":{"count":82},"Safeway":{"count":53},"Delta":{"count":144},"H-E-B Gas":{"count":161},"Kroger Fuel":{"count":53},"Sinopec Fuel":{"count":112},"Posto Shell":{"count":94},"RaceTrac":{"count":71},"BR":{"count":149},"Costco Gas":{"count":58},"Murphy USA":{"count":135},"پمپ گاز":{"count":62},"Royal Farms":{"count":64},"Нефтьмагистраль":{"count":64},"PT":{"count":138},"Uno":{"count":134},"Independent Fuel Station":{"count":56},"エネオス":{"count":68},"P T":{"count":62},"Pecsa":{"count":54},"Bangchak":{"count":68},"CNG":{"count":315},"Posto":{"count":64},"NP":{"count":67},"Posto Atem":{"count":58},"GNV":{"count":79},"Minipump":{"count":116},"Petroperu":{"count":84},"Petrochina":{"count":103}},"place_of_worship":{"Saint Mary":{"count":99},"All Saints":{"count":410},"St Andrew's":{"count":60},"Catholic Church":{"count":173},"Christ Church":{"count":366},"Saint Mary's":{"count":101},"Holy Trinity":{"count":221},"St Mary's Church":{"count":183},"Saint Marks Church":{"count":196},"St Mary":{"count":138},"Trinity Baptist Church":{"count":202},"Sacred Heart Church":{"count":213},"St Peter":{"count":93},"All Saints Church":{"count":217},"Northside Baptist Church":{"count":69},"Saint John the Baptist":{"count":58},"Zion Baptist Church":{"count":71},"Trinity Methodist Church":{"count":93},"Central Baptist Church":{"count":206},"Sacred Heart Catholic Church":{"count":232},"Kingdom Hall":{"count":340},"The Church of Jesus Christ of Latter-day Saints":{"count":3095},"Salvation Army":{"count":150},"Baptist Church":{"count":166},"St John the Baptist":{"count":138},"Saint Mary the Virgin":{"count":70},"Marienkapelle":{"count":338},"Neuapostolische Kirche":{"count":771},"St Mary the Virgin":{"count":164},"Seventh Day Adventist":{"count":65},"St. Mary's Church":{"count":105},"Friedhofskapelle":{"count":810},"Faith Baptist Church":{"count":241},"Grace Lutheran Church":{"count":253},"Church of God":{"count":786},"Kingdom Hall of Jehovah's Witnesses":{"count":1029},"United Reformed Church":{"count":73},"St. Mary's":{"count":72},"St Peter's":{"count":103},"St Andrew's Church":{"count":70},"Kapelle":{"count":1666},"St. Josef":{"count":224},"St. Laurentius":{"count":259},"Church of the Good Shepherd":{"count":99},"Friedenskirche":{"count":264},"Hubertuskapelle":{"count":157},"St Mary's":{"count":218},"Kingdom Hall of Jehovahs Witnesses":{"count":601},"Saint Mary's Church":{"count":111},"Pauluskirche":{"count":110},"Martinskirche":{"count":139},"St Nicholas":{"count":107},"Erlöserkirche":{"count":137},"Saint Pauls Church":{"count":517},"Saint Josephs Church":{"count":131},"Mariä Himmelfahrt":{"count":225},"Heilig-Geist-Kirche":{"count":90},"St. Peter und Paul":{"count":314},"Königreichssaal":{"count":88},"Auferstehungskirche":{"count":159},"St. Johannes Baptist":{"count":68},"Herz Jesu":{"count":95},"Kirche":{"count":302},"Grace Chapel":{"count":54},"Katholische Kirche":{"count":172},"Sankt Michael":{"count":123},"Christuskirche":{"count":423},"St. Michael":{"count":430},"Lutherkirche":{"count":118},"Church":{"count":406},"Evangelische Kirche":{"count":671},"Johanniskirche":{"count":54},"St. Georg":{"count":319},"Sankt Laurentius":{"count":65},"St. Stephanus":{"count":98},"Chiesa di Sant'Antonio":{"count":86},"Église":{"count":1017},"Saint Joseph Church":{"count":136},"Bible Baptist Church":{"count":166},"Church of Christ":{"count":1545},"Saint Peter":{"count":63},"Kreuzkirche":{"count":172},"Seventh Day Adventist Church":{"count":560},"St. Sebastian":{"count":107},"Saint Peters Church":{"count":231},"Methodist Church":{"count":236},"Heilig-Kreuz-Kirche":{"count":66},"Herz-Jesu-Kirche":{"count":111},"Maria Hilf":{"count":55},"Shady Grove Church":{"count":323},"St. Johannes der Täufer":{"count":129},"Thomaskirche":{"count":57},"Stadtkirche":{"count":108},"Heilige Familie":{"count":56},"Jehovas Zeugen":{"count":72},"Versöhnungskirche":{"count":83},"St Mary Magdalene":{"count":57},"Sankt Marien":{"count":87},"Sankt Martin":{"count":145},"St James":{"count":102},"St Michael and All Angels":{"count":59},"Waldkapelle":{"count":72},"Sankt Nikolaus":{"count":102},"St. Joseph":{"count":111},"Friends Meeting House":{"count":60},"St. Katharina":{"count":76},"Stupa":{"count":85},"Jézus Szíve-templom":{"count":80},"Concord Church":{"count":185},"Congregational Church":{"count":58},"Chapelle":{"count":480},"Церковь":{"count":265},"Kreuzkapelle":{"count":69},"Heilig Kreuz":{"count":117},"St. Jakob":{"count":56},"St. Leonhard":{"count":108},"St John the Evangelist":{"count":82},"Anglican Church":{"count":92},"Heilig Geist":{"count":54},"St Peter's Church":{"count":95},"St. Ulrich":{"count":95},"Emmanuel Church":{"count":183},"Johanneskirche":{"count":191},"Martin-Luther-Kirche":{"count":128},"Foursquare Gospel Church":{"count":57},"St. Marien":{"count":216},"Liebfrauenkirche":{"count":73},"Seventh-Day Adventist Church":{"count":52},"Biserica":{"count":2164},"Evangelisch-Freikirchliche Gemeinde":{"count":99},"Marienkirche":{"count":192},"Iglesia de San Juan":{"count":56},"St. Antonius":{"count":121},"St Paul's":{"count":53},"St John's Church":{"count":55},"St. Jakobus":{"count":106},"St Peters":{"count":54},"Masjid":{"count":1950},"Holy Trinity Church":{"count":202},"Redeemer Lutheran Church":{"count":112},"St Andrew":{"count":68},"Sankt Georg":{"count":97},"St. Andreas":{"count":139},"St Andrews":{"count":54},"Αγία Παρασκευή":{"count":73},"San Francesco":{"count":92},"St. Martin":{"count":411},"St. Nikolaus":{"count":340},"Maria Himmelfahrt":{"count":115},"Synagogue":{"count":83},"St. Johann Baptist":{"count":58},"The Salvation Army":{"count":86},"Iglesia de San Andrés":{"count":58},"Surau":{"count":159},"Trinity Church":{"count":456},"Mariengrotte":{"count":90},"Saint Andrews Church":{"count":121},"熊野神社":{"count":99},"Chiesa di San Martino":{"count":133},"Iglesia":{"count":962},"Mosque":{"count":590},"Προφήτης Ηλίας":{"count":90},"Calvary Church":{"count":447},"St. Peter":{"count":161},"St. Bartholomäus":{"count":139},"Sankt Andreas":{"count":55},"Церковь Преображения Господня":{"count":100},"Saint Peter's Church":{"count":53},"Chapelle Sainte-Anne":{"count":92},"First Baptist Church":{"count":2346},"Igreja Matriz":{"count":213},"Saint Josephs Catholic Church":{"count":124},"Église Saint-Michel":{"count":229},"St. Johannes":{"count":160},"Sankt Josef":{"count":74},"Chiesa di San Giuseppe":{"count":137},"St. Bonifatius":{"count":108},"Chiesa di San Giorgio":{"count":134},"Chiesa di San Giovanni Battista":{"count":180},"St. Barbara":{"count":85},"New Life Church":{"count":84},"Iglesia ni Cristo":{"count":237},"Iglesia Ni Cristo":{"count":299},"Calvary Baptist Church":{"count":547},"United Methodist Church":{"count":638},"Bethany Baptist Church":{"count":105},"Saint Francis Church":{"count":54},"Holy Family Church":{"count":74},"Wesleyan Church":{"count":101},"United Pentecostal Church":{"count":158},"Trinity Lutheran Church":{"count":458},"Antoniuskapelle":{"count":94},"Emmanuel Baptist Church":{"count":149},"Chapel":{"count":230},"San Pietro":{"count":85},"St. Ägidius":{"count":57},"Iglesia de San Martín":{"count":66},"Ermita de San Roque":{"count":125},"Igreja Batista":{"count":59},"St. Elisabeth":{"count":102},"St. Anna":{"count":124},"Dorfkirche":{"count":226},"Assembleia de Deus":{"count":64},"St. Martinus":{"count":65},"Hope Church":{"count":65},"Biserică":{"count":709},"St. Pankratius":{"count":79},"Temple":{"count":504},"Biserica Ortodoxă":{"count":62},"Holy Family Catholic Church":{"count":94},"諏訪神社":{"count":86},"Chiesa di San Rocco":{"count":265},"Chiesa":{"count":203},"八坂神社":{"count":66},"Klosterkirche":{"count":76},"Église Saint-Pierre":{"count":997},"Sankt Peter und Paul":{"count":67},"St. Maria":{"count":82},"New Jerusalem Church":{"count":51},"San Martino":{"count":79},"Église Saint-Antoine":{"count":80},"St Michael's":{"count":61},"St. Vitus":{"count":106},"Santo Stefano":{"count":52},"San Giovanni Battista":{"count":78},"Markuskirche":{"count":65},"Calvary Chapel":{"count":57},"Dreifaltigkeitskirche":{"count":93},"Kapel":{"count":97},"Église Saint-Martin":{"count":1353},"Ermita de San Miguel":{"count":65},"Церковь Троицы Живоначальной":{"count":227},"Bethlehem Lutheran Church":{"count":88},"St. Johannis":{"count":60},"Maria Königin":{"count":56},"Chiesa di Sant'Andrea":{"count":57},"Mariä Heimsuchung":{"count":65},"Zion Lutheran Church":{"count":226},"Pfarrkirche":{"count":106},"Église Saint-Hilaire":{"count":109},"Holy Cross Church":{"count":86},"St. Margaretha":{"count":52},"Chiesa di Santa Lucia":{"count":70},"Ermita":{"count":109},"Saint Mary's Catholic Church":{"count":65},"Église Saint-Christophe":{"count":84},"Königreichssaal Jehovas Zeugen":{"count":59},"Trauerhalle":{"count":123},"Iglesia Parroquial":{"count":62},"Church of God of Prophecy":{"count":232},"Mount Olive Baptist Church":{"count":159},"Chiesa di San Giovanni":{"count":53},"Michaelskirche":{"count":59},"Άγιος Γεώργιος":{"count":97},"Reformierte Kirche":{"count":97},"Aussegnungshalle":{"count":106},"Wesley Church":{"count":72},"First United Methodist Church":{"count":880},"稲荷神社":{"count":85},"San Michele Arcangelo":{"count":57},"St. Mauritius":{"count":55},"svatý Václav":{"count":68},"San Lorenzo":{"count":79},"Iglesia de San Juan Bautista":{"count":90},"Evangelical Free Church":{"count":81},"Providence Church":{"count":252},"Église Saint-Vincent":{"count":105},"Chapelle Saint-Roch":{"count":106},"San Giuseppe":{"count":80},"First Presbyterian Church":{"count":1196},"Église Saint-Denis":{"count":138},"church":{"count":64},"Pentecostal Church":{"count":78},"Fellowship Baptist Church":{"count":105},"First Church of the Nazarene":{"count":306},"Iglesia Evangelica":{"count":74},"Iglesia de Nuestra Señora de la Asunción":{"count":66},"Mariä Geburt":{"count":52},"Grace Baptist Church":{"count":272},"Hope Lutheran Church":{"count":88},"San Giorgio":{"count":57},"St. Stephan":{"count":89},"Église Saint-Éloi":{"count":52},"Église Notre-Dame":{"count":548},"Chapelle Saint-Jean":{"count":53},"Église Sainte-Anne":{"count":71},"Chiesa di San Lorenzo":{"count":132},"Église Saint-Aubin":{"count":75},"Chapelle Saint-Pierre":{"count":51},"Saint Michaels Church":{"count":71},"Messiah Lutheran Church":{"count":75},"Madonna della Neve":{"count":58},"Saint Pauls Lutheran Church":{"count":141},"Church of God in Christ":{"count":141},"Immaculate Conception Catholic Church":{"count":86},"First Church of Christ Scientist":{"count":450},"Chiesa di Santa Maria Assunta":{"count":138},"New Apostolic Church":{"count":92},"Free Methodist Church":{"count":143},"Iglesia de Dios":{"count":66},"Apostolic Church":{"count":75},"Chiesa di San Francesco":{"count":108},"Ermita de San Antonio":{"count":53},"Église Saint-Joseph":{"count":114},"Church of the Nazarene":{"count":509},"Community of Christ":{"count":180},"Parroquia":{"count":92},"Santa Maria":{"count":202},"Мечеть":{"count":313},"Königreichsaal":{"count":54},"Ev. Kirche":{"count":122},"Iglesia de San Miguel":{"count":105},"Saint Paul Church":{"count":250},"Antioch Church":{"count":545},"Assembly of God Church":{"count":273},"Bethany Church":{"count":329},"Bethel Church":{"count":1055},"Bethel Lutheran Church":{"count":53},"Bethesda Church":{"count":94},"Bethlehem Church":{"count":499},"Beulah Church":{"count":179},"Christian Church":{"count":83},"Church of the Brethren":{"count":51},"Church of Jesus Christ":{"count":53},"Community Church":{"count":171},"County Line Church":{"count":91},"Ebenezer Church":{"count":349},"Evergreen Church":{"count":88},"Faith Lutheran Church":{"count":190},"Faith Church":{"count":203},"Fairview Church":{"count":388},"Fellowship Church":{"count":127},"Grace Church":{"count":312},"First Congregational Church":{"count":391},"Friendship Church":{"count":484},"Full Gospel Church":{"count":81},"Friends Church":{"count":51},"Harmony Church":{"count":162},"Immanuel Church":{"count":141},"Maple Grove Church":{"count":73},"Liberty Church":{"count":322},"Little Zion Church":{"count":71},"Midway Church":{"count":196},"Mount Bethel Church":{"count":57},"Mount Hope Church":{"count":98},"Mount Zion Church":{"count":1084},"Mount Pleasant Church":{"count":508},"Mount Olive Church":{"count":594},"Nazarene Church":{"count":60},"New Hope Church":{"count":701},"Oak Grove Church":{"count":592},"Pleasant Hill Church":{"count":482},"Pilgrim Church":{"count":73},"Pine Grove Church":{"count":292},"Pleasant View Church":{"count":137},"Pleasant Valley Church":{"count":203},"Pleasant Ridge Church":{"count":127},"Riverside Church":{"count":84},"Saint John Church":{"count":148},"Saint James Church":{"count":318},"Saint Lukes Church":{"count":193},"Saint Johns Church":{"count":664},"Saint Luke Church":{"count":87},"Saint Mark Church":{"count":51},"Saint Marys Church":{"count":311},"Saint Mary Church":{"count":64},"Tabernacle Church":{"count":97},"Saint Thomas Church":{"count":76},"Saint Stephens Church":{"count":74},"Salem Church":{"count":475},"Smith Chapel":{"count":80},"Springfield Church":{"count":74},"Union Church":{"count":519},"Union Chapel":{"count":182},"United Church":{"count":90},"Victory Church":{"count":90},"Zion Church":{"count":493},"Macedonia Church":{"count":423},"Saint Joseph Catholic Church":{"count":116},"Saint Pauls Episcopal Church":{"count":140},"Unity Church":{"count":86},"Central Church":{"count":111},"Shiloh Church":{"count":420},"All Saints Episcopal Church":{"count":98},"Saint Johns Catholic Church":{"count":71},"Locust Grove Church":{"count":67},"Greenwood Church":{"count":51},"Jehovah's Witnesses":{"count":69},"Bethel Baptist Church":{"count":255},"Calvary Lutheran Church":{"count":64},"Grace United Methodist Church":{"count":165},"Wesley United Methodist Church":{"count":111},"First Assembly of God Church":{"count":389},"Saint John's Episcopal Church":{"count":61},"Bethany Lutheran Church":{"count":86},"Saint Paul's Lutheran Church":{"count":62},"First Lutheran Church":{"count":195},"Saint John's Lutheran Church":{"count":69},"Bethel African Methodist Episcopal Church":{"count":122},"Church of the Living God":{"count":96},"Chapel Hill Church":{"count":77},"Mount Calvary Church":{"count":158},"First Church of God":{"count":235},"Saint Paul Lutheran Church":{"count":151},"Holy Trinity Lutheran Church":{"count":70},"Immaculate Conception Church":{"count":120},"Immanuel Baptist Church":{"count":127},"Prince of Peace Lutheran Church":{"count":70},"Shiloh Baptist Church":{"count":170},"Christ United Methodist Church":{"count":86},"Community Bible Church":{"count":58},"Trinity United Methodist Church":{"count":230},"Holy Trinity Episcopal Church":{"count":51},"Grace Bible Church":{"count":65},"Grace Episcopal Church":{"count":128},"Good Shepherd Lutheran Church":{"count":131},"First Church of Christ":{"count":81},"Presbyterian Church":{"count":160},"Saint James Episcopal Church":{"count":115},"Community Baptist Church":{"count":110},"Central United Methodist Church":{"count":56},"Trinity Episcopal Church":{"count":221},"First Missionary Baptist Church":{"count":59},"First Reformed Church":{"count":63},"Holy Cross Lutheran Church":{"count":63},"Peace Lutheran Church":{"count":108},"Saint John Lutheran Church":{"count":79},"First Free Will Baptist Church":{"count":51},"Immanuel Lutheran Church":{"count":190},"Faith United Methodist Church":{"count":70},"Berean Baptist Church":{"count":51},"First Methodist Church":{"count":191},"Bethlehem Baptist Church":{"count":97},"Second Baptist Church":{"count":211},"First Christian Church":{"count":663},"Saint Johns Lutheran Church":{"count":150},"Friendship Baptist Church":{"count":176},"Our Savior Lutheran Church":{"count":74},"Saint Marks Episcopal Church":{"count":76},"First United Presbyterian Church":{"count":84},"Christ Episcopal Church":{"count":160},"Saint Johns Episcopal Church":{"count":151},"Grace Community Church":{"count":64},"Liberty Baptist Church":{"count":124},"Pentecostal Church of God":{"count":98},"Saint Matthews Church":{"count":139},"Christ Lutheran Church":{"count":155},"Saint Paul United Methodist Church":{"count":70},"Victory Baptist Church":{"count":97},"Saint James Catholic Church":{"count":54},"Christ Community Church":{"count":56},"Saint Andrews Episcopal Church":{"count":91},"New Hope Baptist Church":{"count":230},"Westminster Presbyterian Church":{"count":150},"Trinity Evangelical Lutheran Church":{"count":57},"New Bethel Baptist Church":{"count":52},"Hopewell Baptist Church":{"count":60},"Pleasant Grove Church":{"count":487},"Mount Zion Baptist Church":{"count":221},"Mount Calvary Baptist Church":{"count":91},"Saint Paul Baptist Church":{"count":77},"Cornerstone Baptist Church":{"count":51},"First Pentecostal Church":{"count":76},"Cornerstone Church":{"count":53},"United Church of Christ":{"count":95},"Crossroads Church":{"count":110},"Covenant Presbyterian Church":{"count":63},"Asbury Church":{"count":64},"Asbury United Methodist Church":{"count":80},"Beech Grove Church":{"count":76},"Berea Church":{"count":59},"Cedar Grove Church":{"count":213},"Center Church":{"count":79},"Corinth Church":{"count":176},"Galilee Church":{"count":91},"Hebron Church":{"count":114},"Hickory Grove Church":{"count":115},"Hopewell Church":{"count":288},"Jerusalem Church":{"count":139},"Lebanon Church":{"count":111},"Macedonia Baptist Church":{"count":138},"New Bethel Church":{"count":216},"New Liberty Church":{"count":57},"New Prospect Church":{"count":88},"New Home Church":{"count":96},"New Salem Church":{"count":132},"New Zion Church":{"count":164},"Mount Zion United Methodist Church":{"count":51},"Mount Gilead Church":{"count":81},"Mount Hebron Church":{"count":56},"Mount Pisgah Church":{"count":139},"Mount Moriah Church":{"count":196},"Mount Nebo Church":{"count":108},"Oak Grove Baptist Church":{"count":90},"Oak Hill Church":{"count":95},"Oakland Church":{"count":60},"Mount Carmel Church":{"count":284},"Mount Olivet Church":{"count":101},"Mount Vernon Church":{"count":152},"Mount Tabor Church":{"count":106},"Rose Hill Church":{"count":75},"Palestine Church":{"count":63},"Rock Springs Church":{"count":51},"Pisgah Church":{"count":72},"Sharon Church":{"count":90},"Union Grove Church":{"count":173},"Saint Patricks Church":{"count":91},"Walnut Grove Church":{"count":102},"Wesley Chapel":{"count":174},"White Oak Church":{"count":82},"Memorial Baptist Church":{"count":57},"Bethel United Methodist Church":{"count":78},"Central Christian Church":{"count":84},"Saint Thomas Episcopal Church":{"count":54},"Saint Marys Catholic Church":{"count":180},"Zion Hill Church":{"count":146},"Saint Patricks Catholic Church":{"count":79},"Mount Pleasant Baptist Church":{"count":76},"Philadelphia Church":{"count":82},"Good Hope Church":{"count":125},"Mount Carmel Baptist Church":{"count":72},"Central Church of Christ":{"count":68},"First Southern Baptist Church":{"count":95},"Union Baptist Church":{"count":131},"Holy Cross Catholic Church":{"count":54},"Central Presbyterian Church":{"count":51},"Trinity Presbyterian Church":{"count":70},"Saint Marys Roman Catholic Church":{"count":54},"Temple Baptist Church":{"count":119},"Saint Peters Episcopal Church":{"count":54},"Antioch Baptist Church":{"count":173},"Sacred Heart Roman Catholic Church":{"count":59},"First United Pentecostal Church":{"count":85},"Holy Trinity Catholic Church":{"count":54},"Calvary United Methodist Church":{"count":65},"Providence Baptist Church":{"count":77},"Mount Sinai Church":{"count":107},"Morning Star Church":{"count":126},"Saint James Baptist Church":{"count":59},"Pleasant Grove Baptist Church":{"count":89},"Pleasant Hill Baptist Church":{"count":68},"Tabernacle Baptist Church":{"count":108},"Morning Star Baptist Church":{"count":72},"Saint Paul African Methodist Episcopal Church":{"count":58},"Saint Peter Church":{"count":62},"Salem Baptist Church":{"count":79},"Highland Church":{"count":61},"Smyrna Church":{"count":69},"Saint Pauls United Methodist Church":{"count":52},"Saint Mary's Roman Catholic Church":{"count":55},"Fairview Baptist Church":{"count":54},"Saint Lukes Episcopal Church":{"count":69},"Église Saint-Jean-Baptiste":{"count":435},"Церковь Рождества Христова":{"count":117},"Pilgrim Rest Church":{"count":80},"Chestnut Grove Church":{"count":64},"Ebenezer Baptist Church":{"count":100},"Enon Church":{"count":68},"Faith Tabernacle":{"count":55},"Holiness Church":{"count":94},"Mill Creek Church":{"count":61},"Mountain View Church":{"count":106},"Oak Ridge Church":{"count":65},"Sardis Church":{"count":86},"Sweet Home Church":{"count":59},"Union Hill Church":{"count":119},"Mount Zion Church (historical)":{"count":68},"Pentecostal Holiness Church":{"count":69},"Liberty Hill Church":{"count":77},"New Hope Church (historical)":{"count":55},"Bethel Church (historical)":{"count":84},"Saint John Baptist Church":{"count":56},"Saint Marys Episcopal Church":{"count":51},"Southside Baptist Church":{"count":94},"Holly Grove Church":{"count":57},"Jones Chapel":{"count":73},"Mount Pilgrim Church":{"count":52},"Pilgrims Rest Church":{"count":68},"Pine Hill Church":{"count":57},"Piney Grove Church":{"count":170},"Poplar Springs Church":{"count":57},"Prospect Church":{"count":98},"Red Hill Church":{"count":72},"Rock Hill Church":{"count":74},"Spring Hill Church":{"count":178},"Beulah Baptist Church":{"count":51},"Magnolia Church":{"count":57},"Westside Baptist Church":{"count":55},"First Assembly of God":{"count":61},"First Church of Christ, Scientist":{"count":64},"Église Saint-André":{"count":176},"Kaplica":{"count":269},"Ganesh Temple":{"count":56},"Ganesha Temple":{"count":53},"Iglesia de San Francisco":{"count":55},"Igreja Universal do Reino de Deus":{"count":114},"Calvaire":{"count":53},"Kaplička":{"count":56},"Santa Lucia":{"count":69},"temple":{"count":68},"Hanuman Temple":{"count":172},"Église Saint-Étienne":{"count":281},"Часовня":{"count":319},"Szent Mihály-templom":{"count":60},"Chiesa di Sant'Anna":{"count":81},"Chiesa di San Sebastiano":{"count":69},"八幡神社":{"count":139},"Église Saint-Léger":{"count":155},"Chiesa di Santa Maria":{"count":65},"Церковь Михаила Архангела":{"count":142},"Церковь Покрова Пресвятой Богородицы":{"count":288},"San Michele":{"count":83},"Église Saint-Didier":{"count":51},"biserica":{"count":192},"San Rocco":{"count":157},"Jakobuskirche":{"count":53},"Церковь Рождества Пресвятой Богородицы":{"count":173},"مسجد":{"count":485},"Capilla":{"count":173},"Église Sainte-Marie-Madeleine":{"count":72},"Άγιος Νικόλαος":{"count":99},"Église Saint-Nicolas":{"count":283},"Assembléia de Deus":{"count":177},"Salão do Reino das Testemunhas de Jeová":{"count":64},"Chiesa di San Michele":{"count":85},"Salón del Reino de los Testigos de Jehová":{"count":90},"Église Saint-Julien":{"count":104},"Chiesa di San Pietro":{"count":114},"Церковь Николая Чудотворца":{"count":366},"Református templom":{"count":357},"Saint-Pierre":{"count":55},"Церковь Петра и Павла":{"count":71},"San Bartolomeo":{"count":57},"Chapelle Notre-Dame":{"count":62},"Hanuman Mandir":{"count":54},"Mosquée":{"count":587},"Церковь Иконы Божией Матери Казанская":{"count":88},"Iglesia de Santa María":{"count":106},"Saint-Martin":{"count":70},"Nanebevzetí Panny Marie":{"count":128},"Église Saint-Sébastien":{"count":67},"Церковь Вознесения Господня":{"count":95},"Shiva Temple":{"count":76},"Wat":{"count":124},"Chapelle Saint-Joseph":{"count":54},"Sant'Anna":{"count":56},"Церковь Успения Пресвятой Богородицы":{"count":176},"Chiesa di San Bartolomeo":{"count":99},"Iglesia de San Pedro":{"count":114},"Kaplica cmentarna":{"count":558},"kaplica cmentarna":{"count":95},"mosque":{"count":63},"The Church of Jesus Christ of Latter Day Saints":{"count":64},"Chiesa della Santissima Trinità":{"count":59},"masjid":{"count":224},"神明社":{"count":67},"Igreja Católica":{"count":87},"Церковь Богоявления Господня":{"count":72},"Chiesa di San Giacomo":{"count":61},"Église Saint-Jacques":{"count":115},"Evangélikus templom":{"count":113},"Église Saint-Maurice":{"count":197},"Église Saint-Georges":{"count":171},"Église Saint-Barthélémy":{"count":54},"mosquée":{"count":67},"Chiesa del Carmine":{"count":52},"Chiesa dei Santi Pietro e Paolo":{"count":73},"Ermita de San Pedro":{"count":54},"Igreja":{"count":89},"Masjid Al Ikhlas":{"count":54},"Masjid Nurul Iman":{"count":80},"Masjid Nurul Huda":{"count":79},"Kościół pw. Najświętszego Serca Pana Jezusa":{"count":98},"Gereja":{"count":100},"Chiesa di Sant'Antonio Abate":{"count":71},"Sant'Antonio":{"count":81},"Santa Maria Assunta":{"count":109},"Église Saint-Vaast":{"count":83},"Camii":{"count":95},"Église Saint-Jean":{"count":79},"Sala Królestwa Świadków Jehowy":{"count":82},"Église Saint-Laurent":{"count":236},"Iglesia Catolica":{"count":80},"土地公廟":{"count":56},"Церква":{"count":63},"Capela":{"count":81},"Церковь Георгия Победоносца":{"count":83},"Церковь Воскресения Христова":{"count":78},"Eglise":{"count":79},"Kościół pw. Wniebowzięcia Najświętszej Maryi Panny":{"count":68},"Церковь Илии Пророка":{"count":59},"مسجد جامع":{"count":65},"Церковь Спаса Преображения":{"count":51},"Iglesia de Jesucristo de los Santos de los Últimos Días":{"count":60},"წმინდა გიორგი (St. Giorgi)":{"count":62},"Iglesia Cristiana Evangélica":{"count":53},"Église de l'Assomption":{"count":114},"Église Notre-Dame de l'Assomption":{"count":114},"Église Saint-Louis":{"count":64},"Église Saint-Sauveur":{"count":55},"Chiesa di San Michele Arcangelo":{"count":90},"Mesjid":{"count":330},"Mushalla":{"count":215},"Iglesia Católica":{"count":56},"Igreja Assembléia de Deus":{"count":57},"Άγιος Δημήτριος":{"count":57},"Iglesia de San Esteban":{"count":56},"Narození Panny Marie":{"count":54},"Église Saint-Sulpice":{"count":89},"La Iglesia de Jesucristo de los Santos de los Últimos Días":{"count":53},"Chiesa di San Biagio":{"count":56},"Église Saint-Saturnin":{"count":56},"monastery":{"count":254},"Церковь Казанской иконы Божией Матери":{"count":83},"pilone votivo":{"count":64},"mesjid":{"count":173},"Église Sainte-Madeleine":{"count":91},"Église Saint-Pierre et Saint-Paul":{"count":120},"Chiesa di Santo Stefano":{"count":80},"Sant Miquel":{"count":71},"福德祠":{"count":62},"Musholla":{"count":164},"Église Notre-Dame-de-l'Assomption":{"count":187},"Църква":{"count":52},"福德宮":{"count":63},"Chiesa di San Domenico":{"count":54},"Magyarok Nagyasszonya-templom":{"count":64},"Mushola":{"count":172},"Nagyboldogasszony-templom":{"count":98},"Église Saint-Germain":{"count":138},"Église Saint-Roch":{"count":53},"Nejsvětější Trojice":{"count":85},"MASJID":{"count":66},"Église Saint-Médard":{"count":114},"Mushollah":{"count":51},"Sant Pere":{"count":54},"pagoda":{"count":306},"Église Saint-Symphorien":{"count":64},"Kościół pw. Miłosierdzia Bożego":{"count":56},"Unknown Mosque":{"count":55},"Église Saint-Pierre-ès-Liens":{"count":65},"Kovil":{"count":161},"Église Saint-Blaise":{"count":71},"Église Saint-Barthélemy":{"count":77},"Kościół pw. Podwyższenia Krzyża Świętego":{"count":63},"Szent István király templom":{"count":66},"Ref. templom":{"count":191},"Église Saint-Rémy":{"count":77},"IGLESIA CATOLICA":{"count":56},"Szent István király-templom":{"count":111},"Église Saint-Paul":{"count":92},"Église Saint-Rémi":{"count":67},"Kisboldogasszony-templom":{"count":70},"Szent Anna-templom":{"count":64},"Église Saint-Quentin":{"count":66},"svätého Michala":{"count":68},"Église du Sacré-Cœur":{"count":55},"Szentháromság-templom":{"count":104},"Nagyboldogasszony templom":{"count":52},"Szent Kereszt felmagasztalása-templom":{"count":61}},"fast_food":{"Quick":{"count":489},"McDonald's":{"count":16493,"tags":{"cuisine":"burger"}},"Subway":{"count":9310,"tags":{"cuisine":"sandwich"}},"Burger King":{"count":5558,"tags":{"cuisine":"burger"}},"Pizza Hut":{"count":1320,"tags":{"cuisine":"pizza"}},"Ali Baba":{"count":90},"Hungry Jacks":{"count":239,"tags":{"cuisine":"burger"}},"Red Rooster":{"count":179},"KFC":{"count":4912,"tags":{"cuisine":"chicken"}},"Chowking":{"count":213},"Jollibee":{"count":637},"Five Guys":{"count":310},"肯德基":{"count":174},"Domino's Pizza":{"count":1811,"tags":{"cuisine":"pizza"}},"Hesburger":{"count":156},"Wendy's":{"count":2624,"tags":{"cuisine":"burger"}},"Steers":{"count":168},"Arby's":{"count":1231},"A&W":{"count":497},"Tim Hortons":{"count":406},"Dairy Queen":{"count":1243},"Fish & Chips":{"count":159},"麦当劳":{"count":97},"Harvey's":{"count":138},"麥當勞":{"count":168},"Pizza Pizza":{"count":361},"Istanbul Kebab":{"count":53},"Kotipizza":{"count":77},"Jack in the Box":{"count":815,"tags":{"cuisine":"burger"}},"KFC/Taco Bell":{"count":59},"Istanbul":{"count":86},"Kochlöffel":{"count":76},"Pita Pit":{"count":110},"Telepizza":{"count":267},"Hallo Pizza":{"count":93},"Qdoba":{"count":71},"Carl's Jr.":{"count":482,"tags":{"cuisine":"burger"}},"Quiznos":{"count":336,"tags":{"cuisine":"sandwich"}},"Wimpy":{"count":156},"Sonic":{"count":1004,"tags":{"cuisine":"burger"}},"Rally's":{"count":61},"Taco Bell":{"count":2528,"tags":{"cuisine":"mexican"}},"Pizza Nova":{"count":83},"Papa John's":{"count":626,"tags":{"cuisine":"pizza"}},"Max":{"count":52},"Nordsee":{"count":188},"Mr. Sub":{"count":140},"Panera Bread":{"count":103},"Krispy Kreme":{"count":60},"Chipotle":{"count":542,"tags":{"cuisine":"mexican"}},"Макдоналдс":{"count":394,"tags":{"name:en":"McDonald's"}},"マクドナルド":{"count":1078,"tags":{"name:en":"McDonald's","cuisine":"burger"}},"ケンタッキーフライドチキン":{"count":302,"tags":{"name:en":"KFC","cuisine":"chicken"}},"Food Court":{"count":58},"Dunkin' Donuts":{"count":645,"tags":{"cuisine":"donut"}},"Asia Wok":{"count":52},"In-N-Out Burger":{"count":115},"松屋":{"count":542,"tags":{"name:en":"Matsuya"}},"Jimmy John's":{"count":379,"tags":{"cuisine":"sandwich"}},"Hardee's":{"count":511,"tags":{"cuisine":"burger"}},"Waffle House":{"count":67},"Bistro":{"count":64},"Quiznos Sub":{"count":56},"Jamba Juice":{"count":120},"Робин Сдобин":{"count":115},"Baskin-Robbins":{"count":200,"tags":{"amenity":"ice_cream"}},"くら寿司":{"count":97},"吉野家":{"count":403},"Taco Time":{"count":135},"モスバーガー":{"count":449,"tags":{"name:en":"MOS BURGER"}},"すき家":{"count":493,"tags":{"name:en":"SUKIYA"}},"CoCo壱番屋":{"count":203},"スシロー":{"count":94},"Sibylla":{"count":70},"The Pizza Company":{"count":58},"Firehouse Subs":{"count":115},"Little Caesar's":{"count":62},"Papa Murphy's":{"count":70},"Little Caesars":{"count":393,"tags":{"cuisine":"pizza"}},"El Pollo Loco":{"count":112},"Del Taco":{"count":214},"White Castle":{"count":126},"Boston Market":{"count":100},"Chick-fil-A":{"count":720,"tags":{"cuisine":"chicken"}},"Panda Express":{"count":477,"tags":{"cuisine":"chinese"}},"Checkers":{"count":83},"Wienerschnitzel":{"count":53},"ミスタードーナツ":{"count":172},"Whataburger":{"count":760},"Cold Stone Creamery":{"count":71},"Greenwich":{"count":69},"Habib's":{"count":72},"Culver's":{"count":497},"Bob's":{"count":69},"ロッテリア":{"count":83},"Church's Chicken":{"count":207},"Popeye's":{"count":374,"tags":{"cuisine":"chicken"}},"Five Guys Burgers and Fries":{"count":54},"Jersey Mike's Subs":{"count":64},"Long John Silver's":{"count":176},"Kiosk":{"count":56},"Booster Juice":{"count":58},"Burger Machine":{"count":52},"Lotteria":{"count":56},"Schlotzsky's Deli":{"count":274},"Pizza Hut Delivery":{"count":59},"Pollo Campero":{"count":115},"Шаурма":{"count":151},"Taco John's":{"count":119},"SubWay":{"count":52},"Bojangles":{"count":70},"Taco Cabana":{"count":53},"New York Pizza":{"count":53},"Русский Аппетит":{"count":120},"Теремок":{"count":117},"かっぱ寿司":{"count":76},"Zaxby's":{"count":139},"Kebabai":{"count":56},"オリジン弁当":{"count":89},"なか卯":{"count":156},"DQ":{"count":52},"Бургер Кинг":{"count":85},"Бистро":{"count":51},"サブウェイ":{"count":73},"Шаверма":{"count":66},"ほっともっと":{"count":133},"幸楽苑":{"count":67},"摩斯漢堡":{"count":61},"СтарДогс":{"count":72},"Pollo Granjero":{"count":62},"Pinulito":{"count":57}},"restaurant":{"Pizza Hut":{"count":2161,"tags":{"cuisine":"pizza"}},"Pizzeria Italia":{"count":53},"Hirsch":{"count":84},"Shakey's":{"count":53},"Little Chef":{"count":66},"Zur Krone":{"count":93},"Deutsches Haus":{"count":89},"Krone":{"count":178},"Akropolis":{"count":197},"Schützenhaus":{"count":147},"Wagamama":{"count":94},"Kreuz":{"count":85},"Waldschänke":{"count":53},"Pizza Express":{"count":380},"Jägerhof":{"count":55},"La Piazza":{"count":111},"Adler":{"count":158},"La Boucherie":{"count":72},"Lamm":{"count":68},"Zur Sonne":{"count":72},"Zur Linde":{"count":219},"La Pergola":{"count":72},"Panorama":{"count":89},"Shanghai":{"count":89},"Red Lobster":{"count":371},"Zum Löwen":{"count":82},"Swiss Chalet":{"count":148},"Frankie & Benny's":{"count":137},"Hooters":{"count":168},"Sternen":{"count":86},"Hirschen":{"count":88},"Ali Baba":{"count":51},"Denny's":{"count":737},"Sonne":{"count":116},"Ratskeller":{"count":162},"La Cantina":{"count":90},"El Greco":{"count":98},"Gasthof zur Post":{"count":96},"Löwen":{"count":134},"Lotus":{"count":77},"La Pataterie":{"count":96},"Syrtaki":{"count":61},"Bella Napoli":{"count":75},"Oasis":{"count":62},"Mandarin":{"count":82},"Nando's":{"count":338},"Zizzi":{"count":87},"Rhodos":{"count":88},"Bären":{"count":72},"Gasthaus Adler":{"count":66},"Pomodoro":{"count":52},"Lindenhof":{"count":90},"Milano":{"count":66},"Dolce Vita":{"count":108},"Kirchenwirt":{"count":92},"Kreta":{"count":67},"Kantine":{"count":99},"Hong Kong":{"count":109},"Ochsen":{"count":94},"Spur":{"count":64},"Applebee's":{"count":845},"Europa":{"count":61},"Flunch":{"count":175},"Zur Post":{"count":125},"China Town":{"count":99},"La Dolce Vita":{"count":118},"Waffle House":{"count":421},"Gasthaus Krone":{"count":89},"Linde":{"count":115},"Outback Steakhouse":{"count":348},"Dionysos":{"count":80},"Frohsinn":{"count":51},"Kelsey's":{"count":65},"Boston Pizza":{"count":239},"Mykonos":{"count":79},"Bella Italia":{"count":183},"Olympia":{"count":83},"Zum Hirschen":{"count":51},"China House":{"count":61},"Sizzler":{"count":80},"Grüner Baum":{"count":118},"Taj Mahal":{"count":154},"Delphi":{"count":102},"Casablanca":{"count":54},"Rössli":{"count":85},"Wimpy":{"count":57},"Traube":{"count":68},"La Taverna":{"count":52},"Adria":{"count":59},"Pancake House":{"count":67},"Red Robin":{"count":273},"Golden Dragon":{"count":54},"L'Osteria":{"count":64},"Bahnhof":{"count":53},"Harvester":{"count":67},"Belvedere":{"count":52},"Roma":{"count":75},"Hellas":{"count":63},"Mamma Mia":{"count":104},"La Perla":{"count":82},"Vips":{"count":87},"Tim Hortons":{"count":60},"Santorini":{"count":52},"Poseidon":{"count":131},"Gusto":{"count":59},"Тануки":{"count":55},"Da Vinci":{"count":79},"Toscana":{"count":64},"Hippopotamus":{"count":107},"La Terrazza":{"count":54},"Courtepaille":{"count":145},"Dorfkrug":{"count":54},"Hard Rock Cafe":{"count":94},"Marco Polo":{"count":58},"La Piazzetta":{"count":62},"Zorbas":{"count":53},"Athen":{"count":70},"La Fontana":{"count":53},"Pinocchio":{"count":63},"San Marco":{"count":82},"Portofino":{"count":61},"デニーズ":{"count":178},"La Gondola":{"count":56},"Sphinx":{"count":53},"Sportheim":{"count":103},"ジョリーパスタ":{"count":64},"TGI Friday's":{"count":320},"Gasthaus zur Linde":{"count":54},"餃子の王将":{"count":176},"Engel":{"count":52},"Alte Post":{"count":64},"Carpe Diem":{"count":57},"Pizzeria Roma":{"count":77},"La Casa":{"count":56},"China Garden":{"count":106},"Vapiano":{"count":123},"Bistro":{"count":59},"La Scala":{"count":59},"Telepizza":{"count":66},"Trattoria":{"count":64},"Casa Mia":{"count":63},"Taverna":{"count":52},"IHOP":{"count":643},"Chili's":{"count":556},"Asia":{"count":66},"Athos":{"count":58},"Ruby Tuesday":{"count":270},"Olive Garden":{"count":460},"Ocean Basket":{"count":57},"Mellow Mushroom":{"count":63},"Cracker Barrel":{"count":294},"La Strada":{"count":65},"Panera Bread":{"count":466},"Friendly's":{"count":108},"Buffalo Grill":{"count":255},"Taste of India":{"count":57},"Texas Roadhouse":{"count":199},"ガスト":{"count":431,"tags":{"name:en":"Gusto"}},"牛角":{"count":75},"Schwarzer Adler":{"count":59},"丸亀製麺":{"count":63},"ココス":{"count":119},"ロイヤルホスト":{"count":95},"Sushi Bar":{"count":58},"La Tasca":{"count":51},"Venezia":{"count":57},"ジョナサン":{"count":122},"Léon de Bruxelles":{"count":57},"夢庵":{"count":53},"Mensa":{"count":146},"大戸屋":{"count":51},"El Paso":{"count":54},"Five Guys":{"count":70},"びっくりドンキー":{"count":91},"サイゼリヤ":{"count":233},"MK Restaurants":{"count":51},"Village Inn":{"count":135},"Peking":{"count":69},"Sakura":{"count":109},"Tony Roma's":{"count":55},"restaurant":{"count":60},"El Rancho":{"count":71},"Prezzo":{"count":117},"La Bodega":{"count":51},"バーミヤン":{"count":115},"Mimi's Cafe":{"count":53},"Little Italy":{"count":71},"Boston Market":{"count":80},"La Trattoria":{"count":72},"Bonefish Grill":{"count":66},"Wasabi":{"count":62},"China Wok":{"count":76},"Joe's Crab Shack":{"count":66},"Round Table Pizza":{"count":78},"Buffalo Wild Wings":{"count":365},"Perkins":{"count":140},"La Terrasse":{"count":69},"L'Escale":{"count":54},"Shari's":{"count":70},"Bob Evans":{"count":237},"바다횟집 (Bada Fish Restaurant)":{"count":56},"Mang Inasal":{"count":115},"California Pizza Kitchen":{"count":98},"Da Grasso":{"count":53},"Якитория":{"count":80},"Pizza Ranch":{"count":64},"Golden Corral":{"count":191},"Old Chicago":{"count":51},"Евразия":{"count":95},"Carrabba's Italian Grill":{"count":52},"Noodles & Company":{"count":80},"Canteen":{"count":60},"Kudu":{"count":172},"Cold Stone Creamery":{"count":59},"O'Charley's":{"count":59},"Qdoba":{"count":70},"Campanile":{"count":52},"Jason's Deli":{"count":63},"安楽亭":{"count":53},"LongHorn Steakhouse":{"count":151},"Logan's Roadhouse":{"count":81},"Moe's Southwest Grill":{"count":62},"Sushi":{"count":53},"Sonic":{"count":64,"tags":{"cuisine":"burger"}},"Famous Dave's":{"count":56},"Jimmy John's":{"count":119,"tags":{"cuisine":"sandwich"}},"Hardee's":{"count":51,"tags":{"cuisine":"burger"}},"天下一品":{"count":61},"Little Caesars":{"count":66,"tags":{"cuisine":"pizza"}},"Firehouse Subs":{"count":65},"Steak 'n Shake":{"count":68,"tags":{"cuisine":"burger"}},"ジョイフル":{"count":53},"Dunkin' Donuts":{"count":76,"tags":{"cuisine":"donut"}},"やよい軒":{"count":52},"Ristorante Del Arte":{"count":143},"八方雲集":{"count":94}},"parking":{"Coop":{"count":55},"Wanderparkplatz":{"count":796},"Tesco":{"count":86},"Carpool":{"count":55},"Friedhof":{"count":485},"Park and Ride":{"count":88},"Rathaus":{"count":111},"P1":{"count":357},"P2":{"count":351},"Markt":{"count":77},"Public Parking":{"count":173},"Rewe":{"count":201},"ALDI":{"count":324},"P7":{"count":96},"P8":{"count":62},"Parkplatz":{"count":278},"Car Park":{"count":232},"P9":{"count":56},"Lot D":{"count":91},"Park & Ride":{"count":139},"Marktplatz":{"count":166},"P3":{"count":282},"Parkhaus":{"count":139},"Visitor Parking":{"count":246},"Parking de la Mairie":{"count":105},"Edeka":{"count":142},"Besucherparkplatz":{"count":182},"Friedhofsparkplatz":{"count":165},"Estacionamiento":{"count":214},"Festplatz":{"count":109},"Behindertenparkplatz":{"count":176},"Place de l'Église":{"count":311},"Volksbank":{"count":59},"Sportplatz":{"count":143},"P&R":{"count":59},"Kaufland":{"count":117},"Waldparkplatz":{"count":143},"Bahnhof":{"count":98},"P+R":{"count":150},"Parcare":{"count":300},"Sparkasse":{"count":129},"NETTO":{"count":268},"Tesco Car Park":{"count":59},"Bus":{"count":61},"Norma":{"count":68},"Kirche":{"count":52},"P6":{"count":132},"Kundenparkplatz":{"count":280},"School":{"count":241},"Parkplatz Friedhof":{"count":124},"Place de la Mairie":{"count":229},"Krankenhaus":{"count":55},"parking":{"count":252},"Schulparkplatz":{"count":76},"Place de la République":{"count":137},"Lehrerparkplatz":{"count":189},"Lidl":{"count":544},"P10":{"count":55},"P4":{"count":214},"停車場":{"count":92},"Dorfplatz":{"count":53},"P":{"count":73},"Staff Car Park":{"count":71},"Парковка":{"count":164},"Busparkplatz":{"count":122},"PKW":{"count":59},"LKW":{"count":81},"Parking de la Gare":{"count":125},"Carrefour":{"count":77},"Spar":{"count":69},"Mitarbeiterparkplatz":{"count":110},"Parkplatz Lidl":{"count":60},"Penny":{"count":123},"McDonald's":{"count":166,"tags":{"cuisine":"burger"}},"Disabled Parking":{"count":58},"Anwohnerparkplatz":{"count":68},"Bus Parking":{"count":117},"Pendlerparkplatz":{"count":68},"Gravel Parking Lot, Mille Lacs WMA":{"count":82},"Privatparkplatz":{"count":71},"Parking de la Poste":{"count":52},"Lidl Parkplatz":{"count":78},"Place du 19 Mars 1962":{"count":88},"Place de la Liberté":{"count":55},"P5":{"count":193},"Parcheggio":{"count":198},"counter":{"count":110},"Park":{"count":325},"Car Parking":{"count":159},"Parking du Cimetière":{"count":62},"タイムズ":{"count":870},"Visitor":{"count":60},"Private":{"count":188},"Netto Parkplatz":{"count":51},"Place du Champ de Foire":{"count":63},"Kunden":{"count":65},"Parqueadero":{"count":103},"TIR":{"count":93},"Student Parking":{"count":98},"Faculty Parking":{"count":62},"Parking":{"count":1047},"Esselunga":{"count":66},"Автостоянка":{"count":171},"Place du 8 Mai 1945":{"count":86},"Place du Général de Gaulle":{"count":83},"Billa":{"count":51},"Parking Garage":{"count":81},"Freibad":{"count":57},"Staff Parking":{"count":215},"Паркинг":{"count":88},"Place du Marché":{"count":105},"Parqueo":{"count":122},"PMR":{"count":130},"Besucher":{"count":101},"Estacionamento":{"count":122},"<different> Boat Ramp":{"count":113},"Lot B":{"count":107},"Parking leśny":{"count":63},"Стоянка":{"count":147},"Lot C":{"count":95},"Truck Parking":{"count":144},"Parking Lot":{"count":127},"三井のリパーク":{"count":595},"Lot 6":{"count":72},"Lot 2":{"count":81},"Lot 1":{"count":96},"Lot 5":{"count":84},"Lot 3":{"count":90},"Lot 4":{"count":76},"Place de la Libération":{"count":55},"LKW-Parkplatz":{"count":55},"Aldi Süd":{"count":82},"Aparcamiento":{"count":110},"Parkplatz Netto":{"count":56},"Mieterparkplatz":{"count":180},"P11":{"count":51},"Гаражи":{"count":96},"Church":{"count":90},"Private Parking":{"count":55},"H":{"count":51},"Parking strzeżony":{"count":52},"Parkoló":{"count":82},"Privat":{"count":69},"Mitarbeiter":{"count":51},"Handicapped":{"count":203},"Park Cimitero":{"count":126},"駐車場":{"count":178},"Place de la Gare":{"count":72},"car parking":{"count":96},"Parcheggio disabili":{"count":266},"Employee Parking":{"count":104},"Motorcycle Parking":{"count":62},"miejsce postoju":{"count":66},"Overflow Parking":{"count":69},"پارکینگ":{"count":74},"Disabled":{"count":210},"名鉄協商パーキング":{"count":182},"月極駐車場":{"count":67},"Lot A":{"count":110},"Parcheggio Disabili":{"count":238},"Garaje":{"count":83},"Life Time Fitness Parking":{"count":55},"truck parking":{"count":84},"Lot F":{"count":57},"Lot 7":{"count":61},"truck":{"count":271},"car":{"count":460},"Lot H":{"count":54},"Lot E":{"count":67},"Lot G":{"count":55},"Förhyrda":{"count":58}},"bank":{"Chase":{"count":1355},"Commonwealth Bank":{"count":338},"Citibank":{"count":421},"Barclays":{"count":1203},"Westpac":{"count":297},"NAB":{"count":186},"HSBC":{"count":1571},"ANZ":{"count":331},"Bank of China":{"count":65},"TSB":{"count":198},"BBBank":{"count":55},"Sparkasse":{"count":4663},"UCPB":{"count":108},"PNB":{"count":293},"Metrobank":{"count":309},"BDO":{"count":473},"Volksbank":{"count":2690},"China Bank":{"count":132},"BPI":{"count":529},"Postbank":{"count":575},"NatWest":{"count":773},"بانک ملت":{"count":151},"Raiffeisenbank":{"count":2581},"Nordea":{"count":336},"Landbank":{"count":76},"Yorkshire Bank":{"count":89},"ABSA":{"count":96},"Standard Bank":{"count":137},"FNB":{"count":117},"بانک کشاورزی":{"count":100},"بانک مسکن":{"count":96},"Deutsche Bank":{"count":995},"Santander":{"count":2861},"Commerzbank":{"count":867},"Targobank":{"count":201},"ABN AMRO":{"count":144},"SEB":{"count":131},"Handelsbanken":{"count":239},"Kreissparkasse":{"count":615},"UniCredit Bank":{"count":501},"Monte dei Paschi di Siena":{"count":225},"Banca Popolare di Milano":{"count":76},"Caja Rural":{"count":186},"Sparda-Bank":{"count":284},"VÚB":{"count":103},"Slovenská sporiteľňa":{"count":157},"Банка ДСК":{"count":59},"Bank of Montreal":{"count":137},"Comerica Bank":{"count":55},"KBC":{"count":265},"US Bank":{"count":492},"HypoVereinsbank":{"count":449},"Bank Austria":{"count":151},"Lloyds Bank":{"count":620},"ING":{"count":596},"Erste Bank":{"count":206},"CIBC":{"count":422},"BCA":{"count":65},"Scotiabank":{"count":918},"Caisse d'Épargne":{"count":1426},"Clydesdale Bank":{"count":54},"Bank of Scotland":{"count":115},"Royal Bank of Scotland":{"count":126},"TD Canada Trust":{"count":613},"BMO":{"count":288},"Danske Bank":{"count":152},"Crédit Mutuel de Bretagne":{"count":330},"中国农业银行":{"count":148},"Crédit Agricole":{"count":2267},"LCL":{"count":846},"VR-Bank":{"count":500},"ČSOB":{"count":203},"Česká spořitelna":{"count":233},"BNP Paribas":{"count":1062},"National Bank":{"count":100},"RBC Royal Bank":{"count":104},"Nationwide":{"count":286},"中国建设银行":{"count":105},"Halifax":{"count":316},"BAWAG PSK":{"count":98},"CIBC Banking Centre":{"count":55},"Royal Bank":{"count":83},"Nedbank":{"count":92},"First National Bank":{"count":150},"Rabobank":{"count":557},"Sparkasse KölnBonn":{"count":78},"Swedbank":{"count":241},"Tatra banka":{"count":74},"IberCaja":{"count":201},"Volksbank Raiffeisenbank":{"count":60},"İş Bankası":{"count":89},"Berliner Sparkasse":{"count":67},"Berliner Volksbank":{"count":78},"Wells Fargo":{"count":1643},"Société Générale":{"count":1022},"RBC":{"count":363},"Osuuspankki":{"count":85},"Sparkasse Aachen":{"count":56},"Hamburger Sparkasse":{"count":159},"Cassa di Risparmio del Veneto":{"count":99},"Ziraat Bankası":{"count":106},"Akbank":{"count":85},"Banque Populaire":{"count":715},"BNP Paribas Fortis":{"count":282},"Banco Popular":{"count":543},"Bankia":{"count":529},"La Caixa":{"count":1120},"Credit Suisse":{"count":87},"BRD":{"count":251},"BCR":{"count":193},"BW-Bank":{"count":101},"Komerční banka":{"count":171},"Banco Pastor":{"count":77},"OTP":{"count":345},"Sberbank":{"count":130},"CIC":{"count":645},"Banca Transilvania":{"count":139},"Bancpost":{"count":70},"Maybank":{"count":155},"BBVA":{"count":1146},"Postbank Finanzcenter":{"count":55},"中国银行":{"count":209},"Unicredit Banca":{"count":462},"Crédit Mutuel":{"count":1034},"mBank":{"count":58},"Intesa San Paolo":{"count":135},"ATB Financial":{"count":58},"Belfius":{"count":280},"Piraeus Bank":{"count":59},"Bank of America":{"count":1595},"Standard Chartered":{"count":64},"Intesa Sanpaolo":{"count":66},"Сбербанк":{"count":6219},"Россельхозбанк":{"count":304},"Banc Sabadell":{"count":163},"MetroBank":{"count":82},"Crédit du Nord":{"count":138},"Popular":{"count":68},"Banco Sabadell":{"count":176},"Santander Consumer Bank":{"count":101},"BancoEstado":{"count":106},"Millennium Bank":{"count":397},"State Bank of India":{"count":317},"Banca Popolare di Novara":{"count":66},"Беларусбанк":{"count":510},"ING Bank Śląski":{"count":117},"Targo Bank":{"count":60},"Белинвестбанк":{"count":71},"Kreissparkasse Köln":{"count":68},"Banco BCI":{"count":63},"Banco de Chile":{"count":133},"Приорбанк":{"count":70},"ВТБ24":{"count":454},"UBS":{"count":169},"BPH":{"count":61},"PKO BP":{"count":453},"Казкоммерцбанк":{"count":66},"PSBank":{"count":99},"UnionBank":{"count":100},"RCBC Savings Bank":{"count":79},"EastWest Bank":{"count":66},"Commercial Bank of Ceylon PLC":{"count":97},"Caja España":{"count":63},"Unicaja Banco":{"count":180},"BBK":{"count":100},"RBS":{"count":178},"Bank of Ireland":{"count":142},"BNL":{"count":129},"Stadtsparkasse":{"count":72},"Banco Itaú":{"count":288},"AIB":{"count":86},"Райффайзенбанк":{"count":63},"BZ WBK":{"count":146},"Banco do Brasil":{"count":1063},"Caixa Econômica Federal":{"count":451},"Banca Românească":{"count":52},"Fifth Third Bank":{"count":202},"Banca Popolare di Vicenza":{"count":112},"Wachovia":{"count":53},"K&H Bank":{"count":70},"CIB Bank":{"count":61},"Budapest Bank":{"count":53},"みずほ銀行":{"count":244},"BES":{"count":54},"ICICI Bank":{"count":160},"Credem":{"count":55},"HDFC Bank":{"count":163},"La Banque Postale":{"count":109},"Bangkok Bank":{"count":69},"Bank BPH":{"count":58},"工商银行":{"count":140},"Oberbank":{"count":99},"Oldenburgische Landesbank":{"count":68},"Banco di Sardegna":{"count":72},"BRED":{"count":60},"First Bank":{"count":74},"Banca Popolare di Verona":{"count":56},"OLB":{"count":53},"Banca Popolare di Sondrio":{"count":82},"Cariparma":{"count":60},"Bendigo Bank":{"count":127},"BBVA Bancomer":{"count":97},"Argenta":{"count":114},"AXA":{"count":96},"Axis Bank":{"count":125},"Getin Bank":{"count":97},"CaixaBank":{"count":111},"Pekao SA":{"count":120},"Banca March":{"count":60},"БПС-Сбербанк":{"count":51},"Альфа-Банк":{"count":262},"GE Money Bank":{"count":86},"Белагропромбанк":{"count":157},"Banco Galicia":{"count":78},"Eurobank":{"count":215},"Bankinter":{"count":108},"横浜銀行":{"count":79},"Τράπεζα Πειραιώς":{"count":108},"Bank of New Zealand":{"count":58},"Banca Intesa":{"count":93},"Canara Bank":{"count":168},"Cajamar":{"count":149},"Banamex":{"count":288},"CEC Bank":{"count":95},"Davivienda":{"count":152},"Alpha Bank":{"count":287},"招商银行":{"count":63},"Banque Nationale":{"count":88},"第一銀行":{"count":53},"SBI":{"count":70},"Veneto Banca":{"count":65},"Bank of the West":{"count":140},"Liberbank":{"count":101},"Εθνική Τράπεζα":{"count":88},"Key Bank":{"count":226},"Western Union":{"count":327},"Citizens Bank":{"count":190},"УкрСиббанк":{"count":218},"ProCredit Bank":{"count":51},"ПриватБанк":{"count":919},"RCBC":{"count":125},"Security Bank":{"count":136},"Millenium":{"count":59},"HNB":{"count":60},"三菱東京UFJ銀行":{"count":217},"CajaSur":{"count":72},"ВТБ":{"count":70},"Indian Bank":{"count":60},"Andhra Bank":{"count":55},"Banque populaire":{"count":52},"Ulster Bank":{"count":96},"Bancolombia":{"count":122},"TD Bank":{"count":341},"Caixa":{"count":163},"SunTrust Bank":{"count":129},"Авангард":{"count":58},"Union Bank":{"count":173},"Philippine National Bank":{"count":64},"Bradesco":{"count":553},"Itaú":{"count":525},"Punjab National Bank":{"count":73},"PBZ":{"count":64},"Alior Bank":{"count":154},"中国工商银行":{"count":130},"Novo Banco":{"count":69},"Santander Río":{"count":157},"Райффайзен Банк Аваль":{"count":111},"Yorkshire Building Society":{"count":59},"De Venezuela":{"count":89},"ธนาคารไทยพาณิชย์":{"count":57},"Bancomer":{"count":192},"Banorte":{"count":186},"BOC":{"count":94},"Republic Bank":{"count":65},"Raiffeisen Polbank":{"count":60},"Банк Москвы":{"count":172},"Banco Nacional":{"count":120},"Banco Pichincha":{"count":69},"Syndicate Bank":{"count":69},"Bank Zachodni WBK":{"count":80},"Caja Duero":{"count":80},"Regions Bank":{"count":158},"KeyBank":{"count":80},"Bank of Commerce":{"count":64},"Росбанк":{"count":207},"Открытие":{"count":64},"Бинбанк":{"count":77},"People's Bank":{"count":68},"ПУМБ":{"count":63},"Banco di Napoli":{"count":67},"Bank Spółdzielczy":{"count":333},"Public Bank":{"count":56},"SunTrust":{"count":150},"PNC Bank":{"count":493},"신한은행":{"count":221,"tags":{"name:en":"Sinhan Bank"}},"우리은행":{"count":291,"tags":{"name:en":"Uri Bank"}},"국민은행":{"count":168,"tags":{"name:en":"Gungmin Bank"}},"Газпромбанк":{"count":129},"M&T Bank":{"count":138},"Indian Overseas Bank":{"count":62},"Santander Totta":{"count":186},"Banco de Bogotá":{"count":51},"Ощадбанк":{"count":684},"State Bank of Mysore":{"count":58},"Banco Estado":{"count":110},"Ecobank":{"count":138},"Takarékszövetkezet":{"count":120},"East West Bank":{"count":53},"بانک صادرات":{"count":178},"Banco Azteca":{"count":79},"TCF Bank":{"count":68},"Banco Nación":{"count":123},"Galicia":{"count":58},"Macro":{"count":57},"Πειραιώς":{"count":109},"Промсвязьбанк":{"count":120},"بانک سپه":{"count":119},"بانک ملی":{"count":186},"Уралсиб":{"count":118},"صادرات":{"count":61},"三井住友銀行":{"count":179},"りそな銀行":{"count":122},"Commercial Bank":{"count":53},"BCI":{"count":91},"Banco de Costa Rica":{"count":113},"Hrvatska poštanska banka":{"count":55},"Caixa Geral de Depósitos":{"count":210},"Banco Provincia":{"count":98},"Bank of India":{"count":59},"Umpqua Bank":{"count":70},"BCP":{"count":86},"BB&T":{"count":344},"Capital One":{"count":114},"ABANCA":{"count":79},"Возрождение":{"count":67},"Banco Macro":{"count":79},"МДМ Банк":{"count":59},"Capital One Bank":{"count":68},"BBVA Compass":{"count":60},"Caja Círculo":{"count":69},"CatalunyaCaixa":{"count":110},"One Network Bank":{"count":89},"Occidental de Descuento":{"count":67},"Народный банк":{"count":56},"Bank Mandiri":{"count":130},"Banco de la Nación Argentina":{"count":73},"Mercantil":{"count":116},"PKO Bank Polski":{"count":75},"Русский стандарт":{"count":52},"First Citizens Bank":{"count":69},"Corporation Bank":{"count":61},"Bank of Baroda":{"count":68},"Banco G&T Continental":{"count":86},"U.S. Bank":{"count":69},"Banco de Occidente":{"count":55},"Kasa Stefczyka":{"count":57},"Мособлбанк":{"count":52},"CGD":{"count":56},"Huntington Bank":{"count":74},"Sampath Bank":{"count":72},"Peoples Bank":{"count":151},"建设银行":{"count":78},"Interbank":{"count":68},"Banrisul":{"count":76},"بانک تجارت":{"count":122},"Cбербанк":{"count":79},"BBVA Francés":{"count":75},"ธนาคารกรุงเทพ":{"count":77},"ธนาคารกสิกรไทย":{"count":66},"Millenium BCP":{"count":54},"Montepio":{"count":105},"Provincial":{"count":78},"Bicentenario":{"count":127},"Banesco":{"count":172},"ธนาคารกรุงไทย":{"count":60},"Garanti Bankası":{"count":59},"Совкомбанк":{"count":102},"BNA":{"count":67},"BAC":{"count":74},"Banrural":{"count":58},"BRI":{"count":62},"Banco Industrial":{"count":74},"京都銀行":{"count":67},"Cajero Automatico Bancared":{"count":122},"Banco de Desarrollo Banrural":{"count":84},"Banco Patagonia":{"count":51},"ICBC":{"count":107},"Banco de Venezuela":{"count":53},"Banco de la Nación":{"count":117},"Banco Bradesco":{"count":190},"Bank of Africa":{"count":52},"Sicredi":{"count":64},"ლიბერთი ბანკი":{"count":54,"tags":{"name:en":"Liberty Bank"}},"ملی":{"count":52},"Crédito Agrícola":{"count":79},"Caja Rural de Jaén":{"count":54},"ASB Bank":{"count":51},"농협":{"count":51},"РНКБ":{"count":78},"农业银行":{"count":64},"Bank BRI":{"count":140},"Генбанк":{"count":67},"하나은행":{"count":81},"CityCommerce Bank":{"count":54}},"bureau_de_change":{"Western Union":{"count":119},"Kantor":{"count":106}},"car_rental":{"Europcar":{"count":468},"Budget":{"count":161},"Sixt":{"count":250},"Hertz":{"count":511},"Avis":{"count":481},"Enterprise":{"count":443},"Thrifty":{"count":58},"U-Haul":{"count":74},"ニッポンレンタカー":{"count":87}},"pharmacy":{"Lloyds Pharmacy":{"count":436},"Rowlands Pharmacy":{"count":102},"Boots":{"count":1096},"Marien-Apotheke":{"count":371},"Park-Apotheke":{"count":55},"Mercury Drug":{"count":507},"Löwen-Apotheke":{"count":398},"Superdrug":{"count":157},"Sonnen-Apotheke":{"count":374},"Engel-Apotheke":{"count":143},"Hirsch-Apotheke":{"count":114},"Apoteket":{"count":53},"Stadt-Apotheke":{"count":387},"Markt-Apotheke":{"count":203},"Аптека":{"count":2787},"Brunnen-Apotheke":{"count":77},"Hubertus Apotheke":{"count":124},"Bahnhof Apotheke":{"count":51},"Shoppers Drug Mart":{"count":642},"Pharmacie Centrale":{"count":178},"Alte Apotheke":{"count":99},"Neue Apotheke":{"count":122},"Rathaus-Apotheke":{"count":178},"Gintarinė vaistinė":{"count":116},"Rats-Apotheke":{"count":127},"Rosen-Apotheke":{"count":203},"Eczane":{"count":55},"Pharmasave":{"count":116},"Adler Apotheke":{"count":378},"Bären-Apotheke":{"count":109},"Hirsch Apotheke":{"count":69},"Walgreens":{"count":2896},"Rite Aid":{"count":1293},"Linden-Apotheke":{"count":220},"Bahnhof-Apotheke":{"count":88},"Burg-Apotheke":{"count":77},"Apotheke am Markt":{"count":82},"Schloss-Apotheke":{"count":62},"Jean Coutu":{"count":93},"Pharmaprix":{"count":79},"Pharmacie du Centre":{"count":123},"Farmacias Ahumada":{"count":130},"Stern-Apotheke":{"count":83},"Guardian":{"count":59},"Farmacia Comunale":{"count":167},"Dr.Max":{"count":102},"Cruz Verde":{"count":132},"ГорЗдрав":{"count":65},"Watsons":{"count":67},"Farmacias Cruz Verde":{"count":132},"CVS":{"count":2678},"Sensiblu":{"count":96},"Норма":{"count":89},"Farmacias SalcoBrand":{"count":142},"Фармация":{"count":163},"Pharmacie du Marché":{"count":89},"Pharmacie de la Mairie":{"count":57},"Farmacia Guadalajara":{"count":101},"Apteka":{"count":579},"Pharmacie Principale":{"count":54},"Clicks":{"count":116},"セイジョー":{"count":62},"Аптека №1":{"count":80},"マツモトキヨシ":{"count":171},"Dr. Max":{"count":169},"Вита":{"count":119},"Catena":{"count":88},"Здоровье":{"count":64},"Аптека 36,6":{"count":238},"Радуга":{"count":109},"サンドラッグ":{"count":98},"Pharmacie de la Gare":{"count":100},"Apollo Pharmacy":{"count":58},"Chemist Warehouse":{"count":74},"Rexall":{"count":88},"Первая помощь":{"count":114},"Gyógyszertár":{"count":51},"Ригла":{"count":187},"Droga Raia":{"count":104},"Аптека низьких цін":{"count":60},"Rose Pharmacy":{"count":83},"Dbam o Zdrowie":{"count":51},"Kinney Drugs":{"count":71},"Классика":{"count":91},"Ljekarna":{"count":66},"Фармакор":{"count":103},"Farmàcia":{"count":56},"スギ薬局":{"count":101},"Pague Menos":{"count":55},"Горздрав":{"count":139},"Mēness aptieka":{"count":60},"South Star Drug":{"count":57},"Панацея":{"count":58},"Арніка":{"count":123},"Drogaria São Paulo":{"count":52},"Аптечный пункт":{"count":254},"Невис":{"count":106},"Panvel":{"count":52},"Айболит":{"count":71},"SalcoBrand":{"count":90},"Живика":{"count":58},"Walmart Pharmacy":{"count":84},"Walgreens Pharmacy":{"count":59},"Farmacity":{"count":135},"аптека":{"count":126},"The Generics Pharmacy":{"count":171},"Farmacias del Ahorro":{"count":110},"Farmacias Similares":{"count":84},"Farmatodo":{"count":137},"ツルハドラッグ":{"count":116},"Duane Reade":{"count":78},"Фармленд":{"count":93},"H-E-B Pharmacy":{"count":219},"Планета здоровья":{"count":101},"pharmacie":{"count":62},"А5":{"count":94},"Имплозия":{"count":97},"Eurovaistinė":{"count":83},"Бережная аптека":{"count":58},"36.6":{"count":51},"Benavides":{"count":65},"ドラッグてらしま (Drug Terashima)":{"count":77},"Farmacias Guadalajara":{"count":66},"Drogasil":{"count":93},"Фармакопейка":{"count":53},"Аптека от склада":{"count":52},"クリエイト":{"count":51},"ავერსი (Aversi)":{"count":58},"Inkafarma":{"count":56},"Farmahorro":{"count":51},"ウエルシア":{"count":61},"داروخانه":{"count":58},"丁丁藥局":{"count":72}},"library":{"Stadtbibliothek":{"count":233},"Central Library":{"count":56},"Stadtbücherei":{"count":282},"Médiathèque":{"count":251},"Public Library":{"count":74},"Biblioteca Municipal":{"count":388},"Gemeindebücherei":{"count":138},"Bibliothek":{"count":81},"Biblioteca Comunale":{"count":193},"Library":{"count":536},"Bibliothèque municipale":{"count":203},"Bibliothèque Municipale":{"count":266},"Bibliothèque":{"count":252},"Bücherei":{"count":108},"Biblioteca Pública Municipal":{"count":55},"Bibliotheek":{"count":71},"Библиотека":{"count":369},"Детская библиотека":{"count":208},"Центральная городская библиотека":{"count":52},"Biblioteca":{"count":188},"Miejska Biblioteka Publiczna":{"count":59},"Městská knihovna":{"count":54},"Biblioteka":{"count":71},"Biblioteca comunale":{"count":175},"Biblioteka Publiczna":{"count":68},"Gminna Biblioteka Publiczna":{"count":52},"Центральная библиотека":{"count":69},"Biblioteca Pública":{"count":52},"Бібліотека":{"count":71},"Городская библиотека":{"count":54},"图书馆":{"count":51}},"kindergarten":{"Kindergarten":{"count":980},"Arche Noah":{"count":65},"Waldkindergarten":{"count":101},"Städtischer Kindergarten":{"count":98},"Детский сад №19":{"count":56},"Детский сад №11":{"count":71},"Детский сад №8":{"count":73},"Детский сад №2":{"count":139},"Детский сад №7":{"count":89},"Детский сад №15":{"count":65},"Evangelischer Kindergarten":{"count":214},"Katholischer Kindergarten":{"count":99},"Villa Kunterbunt":{"count":86},"Waldorfkindergarten":{"count":69},"Ev. Kindergarten":{"count":106},"Kindergarten St. Josef":{"count":52},"Kindertagesstätte":{"count":130},"Pusteblume":{"count":55},"École maternelle":{"count":335},"Materská škola":{"count":133},"MŠ":{"count":100},"Детский сад №1":{"count":134},"Детский сад №18":{"count":72},"École Maternelle":{"count":66},"Crèche":{"count":99},"Kindergarten Regenbogen":{"count":61},"Przedszkole":{"count":140},"Mateřská škola":{"count":164},"Детский сад":{"count":812},"детский сад":{"count":77},"Óvoda":{"count":63},"Jardin Infantil":{"count":77},"Детский сад №4":{"count":77},"Nursery School":{"count":110},"Детский сад №3":{"count":112},"Детский сад №14":{"count":69},"Детский сад №5":{"count":95},"Детский сад №10":{"count":69},"Детский сад №29":{"count":51},"Детский сад №22":{"count":55},"Scuola Materna":{"count":60},"Детский сад №25":{"count":53},"Детский сад №6":{"count":85},"Солнышко":{"count":87},"საბავშვო ბაღი (Kindergarten)":{"count":149},"Детский сад №9":{"count":71},"PAUD":{"count":83},"Детский сад №12":{"count":51},"中央保育所":{"count":56},"Детский сад \"Солнышко\"":{"count":54},"Maria Montessori":{"count":91},"Rosaura Zapata":{"count":70},"Federico Froebel":{"count":88},"Детский сад №17":{"count":59},"Gabriela Mistral":{"count":129},"Anganwadi":{"count":85},"Jean Piaget":{"count":82},"Amado Nervo":{"count":64},"Benito Juarez":{"count":89},"Cuauhtemoc":{"count":55},"Educacion Inicial de CONAFE No Escolarizado":{"count":184},"Emiliano Zapata":{"count":60},"Estefania Casta�eda":{"count":53},"Jose Vasconcelos":{"count":71},"Juan Escutia":{"count":83},"Miguel Hidalgo Y Costilla":{"count":57},"Preescolar Comunitario":{"count":409},"CONAFE Preescolar":{"count":91},"Ni�os Heroes":{"count":68},"Sor Juana Ines De La Cruz":{"count":76},"Cursos Comunitarios":{"count":74}},"cafe":{"Starbucks":{"count":6881,"tags":{"cuisine":"coffee_shop"}},"Cafeteria":{"count":436},"Costa":{"count":1104},"Caffè Nero":{"count":247},"Кафе":{"count":364},"Café Central":{"count":100},"Tim Hortons":{"count":1662},"Second Cup":{"count":227},"Country Style":{"count":60},"Bar Centrale":{"count":67},"Dunkin' Donuts":{"count":1300,"tags":{"cuisine":"donut"}},"Espresso House":{"count":95},"Coffee Time":{"count":134},"Eiscafe Dolomiti":{"count":52},"Cafe Coffee Day":{"count":197},"Eiscafe Venezia":{"count":226},"スターバックス":{"count":503,"tags":{"name:en":"Starbucks"}},"タリーズコーヒー":{"count":230},"Coffee House":{"count":62},"Segafredo":{"count":101},"Dolce Vita":{"count":55},"Pret A Manger":{"count":155},"Barista":{"count":53},"Venezia":{"count":52},"Шоколадница":{"count":223},"Peet's Coffee & Tea":{"count":64},"Jamba Juice":{"count":68},"Сказка":{"count":56},"ドトールコーヒーショップ":{"count":488},"Café des Sports":{"count":63},"Internet Cafe":{"count":53},"Coffee Shop":{"count":53},"Bistro":{"count":56},"Столовая":{"count":903},"Tchibo":{"count":172},"Бистро":{"count":65},"The Coffee Club":{"count":62},"Теремок":{"count":56},"Кофе Хауз":{"count":121},"Wayne's Coffee":{"count":51},"星巴克":{"count":93},"The Coffee Bean & Tea Leaf":{"count":69},"Закусочная":{"count":74},"Caribou Coffee":{"count":147},"Уют":{"count":81},"ארומה":{"count":53},"カフェ・ベローチェ":{"count":106},"Кофейня":{"count":56},"Шашлычная":{"count":109},"Кафетерий":{"count":55},"Встреча":{"count":70},"Coffee Fellows":{"count":68},"Havanna":{"count":52},"コメダ珈琲店":{"count":147},"คาเฟ่ อเมซอน":{"count":61},"Traveler's Coffee":{"count":64},"85度C":{"count":80},"Café Amazon":{"count":231},"エクセルシオール カフェ":{"count":56},"カフェ・ド・クリエ":{"count":76,"tags":{"name:en":"Cafe de CRIE"}},"サンマルクカフェ":{"count":150},"Bar Kafe":{"count":154}},"school":{"Школа №17":{"count":105},"Kindergarten":{"count":120},"Základná škola":{"count":96},"Astrid-Lindgren-Schule":{"count":78},"École primaire":{"count":2788},"Albert-Schweitzer-Schule":{"count":84},"Grundschule":{"count":653},"Realschule":{"count":75},"school":{"count":51},"Volkshochschule":{"count":100},"Sunnyside School":{"count":61},"Primary School":{"count":1171},"École primaire Jules Ferry":{"count":78},"Základní škola":{"count":159},"Musikschule":{"count":156},"École Primaire":{"count":184},"École Saint-Joseph":{"count":85},"École maternelle":{"count":880},"Erich-Kästner-Schule":{"count":53},"Hauptschule":{"count":156},"Escola Primária":{"count":66},"ZŠ":{"count":111},"Holy Trinity School":{"count":60},"Школа №21":{"count":69},"Школа №27":{"count":55},"Школа №7":{"count":198},"Школа №11":{"count":132},"Школа №16":{"count":89},"Школа №24":{"count":71},"Школа №22":{"count":76},"Saint Joseph School":{"count":149},"Scuola Materna":{"count":63},"Center School":{"count":118},"Jackson School":{"count":60},"Lincoln School":{"count":288},"Roosevelt School":{"count":118},"Pleasant Valley School":{"count":86},"Garfield Elementary School":{"count":66},"Riverside School":{"count":76},"Gimnazjum nr 1":{"count":57},"École Communale":{"count":98},"Volksschule":{"count":372},"Pestalozzischule":{"count":84},"Scuola Elementare":{"count":201},"Scuole Elementari":{"count":61},"Colegio San José":{"count":64},"Schule":{"count":56},"Средняя школа":{"count":161},"Школа №1":{"count":534},"Trinity School":{"count":86},"Secondary School":{"count":222},"Szkoła":{"count":59},"Saint Johns School":{"count":176},"Schillerschule":{"count":59},"Музыкальная школа":{"count":257},"École élémentaire":{"count":845},"École maternelle publique":{"count":78},"École primaire publique":{"count":144},"Гимназия №1":{"count":93},"École primaire privée Saint-Joseph":{"count":130},"Collège Jean Moulin":{"count":65},"Primarschule":{"count":68},"Emiliano Zapata":{"count":286},"Школа №18":{"count":108},"Школа №2":{"count":481},"Школа №3":{"count":380},"Школа №5":{"count":266},"Гимназия":{"count":80},"Школа №26":{"count":60},"École communale":{"count":56},"Scuola Media":{"count":95},"Escuela":{"count":313},"Miguel Hidalgo":{"count":85},"Turnhalle":{"count":60},"École":{"count":452},"Longfellow Elementary School":{"count":54},"Oak Grove School":{"count":149},"Scuola elementare":{"count":94},"Central High School":{"count":140},"Central Elementary School":{"count":176},"Central School":{"count":222},"Fairview School":{"count":166},"Fairview Elementary School":{"count":61},"Garfield School":{"count":61},"Franklin School":{"count":134},"Franklin Elementary School":{"count":100},"Highland School":{"count":72},"Holy Cross School":{"count":70},"Holy Family School":{"count":75},"Hillcrest Elementary School":{"count":60},"Jefferson Elementary School":{"count":177},"Jackson Elementary School":{"count":52},"Jefferson School":{"count":116},"Immaculate Conception School":{"count":86},"Lincoln Elementary School":{"count":264},"Liberty School":{"count":87},"Longfellow School":{"count":60},"McKinley School":{"count":65},"Maple Grove School":{"count":51},"Pine Grove School":{"count":63},"Pleasant View School":{"count":62},"Pleasant Hill School":{"count":110},"Roosevelt Elementary School":{"count":116},"Saint Josephs School":{"count":166},"Saint James School":{"count":89},"Sacred Heart School":{"count":210},"Saint Pauls School":{"count":76},"Saint Peters School":{"count":83},"Saint Marys School":{"count":272},"Saint Patricks School":{"count":87},"Saint Paul School":{"count":53},"Smith School":{"count":61},"Union School":{"count":131},"Trinity Lutheran School":{"count":51},"Wilson School":{"count":85},"Wilson Elementary School":{"count":63},"Washington School":{"count":225},"Washington Elementary School":{"count":191},"White School":{"count":52},"West Elementary School":{"count":58},"Saint Francis School":{"count":58},"Saint Mary School":{"count":53},"North Elementary School":{"count":56},"McKinley Elementary School":{"count":61},"Brown School":{"count":57},"Miller School":{"count":67},"Mount Pleasant School":{"count":63},"School Number 1":{"count":250},"School Number 4":{"count":137},"School Number 3":{"count":192},"School Number 2":{"count":217},"Highland Elementary School":{"count":52},"Liberty Elementary School":{"count":52},"Bethel School (historical)":{"count":97},"Cedar Grove School (historical)":{"count":71},"Center School (historical)":{"count":87},"Central School (historical)":{"count":70},"Fairview School (historical)":{"count":219},"Friendship School (historical)":{"count":63},"Hickory Grove School (historical)":{"count":59},"Hopewell School (historical)":{"count":63},"Liberty School (historical)":{"count":111},"Mount Olive School (historical)":{"count":55},"Mount Pleasant School (historical)":{"count":77},"Mount Zion School (historical)":{"count":96},"New Hope School (historical)":{"count":95},"Oak Hill School (historical)":{"count":53},"Pine Grove School (historical)":{"count":103},"Pleasant Grove School (historical)":{"count":92},"Pleasant Hill School (historical)":{"count":134},"Salem School (historical)":{"count":72},"Union School (historical)":{"count":157},"Walnut Grove School (historical)":{"count":70},"Oak Grove School (historical)":{"count":261},"Maple Grove School (historical)":{"count":54},"Pleasant Valley School (historical)":{"count":95},"Shady Grove School (historical)":{"count":80},"Shiloh School (historical)":{"count":75},"School Number 3 (historical)":{"count":276},"School Number 4 (historical)":{"count":304},"Antioch School (historical)":{"count":70},"School Number 1 (historical)":{"count":276},"School Number 12 (historical)":{"count":128},"School Number 5 (historical)":{"count":272},"School Number 7 (historical)":{"count":255},"School Number 8 (historical)":{"count":209},"School Number 10 (historical)":{"count":160},"Mount Zion School":{"count":53},"Midway School (historical)":{"count":55},"School Number 15 (historical)":{"count":56},"School Number 2 (historical)":{"count":290},"School Number 9 (historical)":{"count":185},"High School":{"count":62},"School Number 6 (historical)":{"count":263},"School Number 11 (historical)":{"count":130},"School Number 14 (historical)":{"count":71},"School Number 13 (historical)":{"count":91},"Gimnazjum":{"count":96},"Zespół Szkół":{"count":83},"Szkoła Podstawowa":{"count":291},"Школа искусств":{"count":75},"School":{"count":1293},"École Élémentaire":{"count":65},"École Maternelle":{"count":62},"Школа №10":{"count":164},"Школа №19":{"count":92},"Escuela Primaria":{"count":79},"École élémentaire publique":{"count":104},"Ecole":{"count":248},"Школа":{"count":665},"Школа №12":{"count":130},"Elementary School":{"count":64},"Scuola Primaria":{"count":71},"Escola Municipal":{"count":161},"Детская школа искусств":{"count":101},"Groupe Scolaire":{"count":55},"CEM":{"count":183},"Школа №8":{"count":187},"École primaire Jean Jaurès":{"count":61},"Szkoła Podstawowa nr 3":{"count":57},"Школа №14":{"count":116},"Школа №13":{"count":128},"Школа № 1":{"count":126},"Szkoła Podstawowa nr 2":{"count":73},"Colegio":{"count":66},"Szkoła Podstawowa nr 1":{"count":75},"Школа №25":{"count":59},"Школа № 2":{"count":105},"Școala":{"count":51},"École primaire privée Notre-Dame":{"count":63},"Школа №4":{"count":275},"Школа №6":{"count":205},"Школа №15":{"count":113},"EPP":{"count":68},"Школа № 4":{"count":78},"Lycée":{"count":120},"Школа № 6":{"count":52},"Ecole primaire":{"count":107},"Szkoła podstawowa":{"count":77},"Школа № 3":{"count":78},"Sekolah":{"count":184},"Escola Estadual":{"count":57},"Collège privé Saint-Joseph":{"count":56},"Школа №9":{"count":178},"Начальная школа":{"count":77},"Школа №23":{"count":76},"Primaire":{"count":59},"Школа-интернат":{"count":109},"Школа №20":{"count":94},"Школа №31":{"count":51},"市立南小学校":{"count":58},"Ecole Primaire":{"count":57},"Средняя школа №2":{"count":70},"UNIDAD EDUCATIVA":{"count":105},"Средняя школа №1":{"count":59},"Nursery School":{"count":66},"Benito Juarez":{"count":295},"SDN":{"count":287},"市立南中学校":{"count":57},"市立東中学校":{"count":62},"市立西中学校":{"count":52},"SD":{"count":54},"Leona Vicario":{"count":64},"École primaire privée Sainte-Marie":{"count":57},"школа":{"count":72},"ESCUELA":{"count":224},"Escola":{"count":70},"École primaire privée":{"count":64},"Általános iskola":{"count":106},"Adolfo Lopez Mateos":{"count":139},"Amado Nervo":{"count":85},"Cuauhtemoc":{"count":152},"Gregorio Torres Quintero":{"count":54},"Guadalupe Victoria":{"count":58},"Ignacio Zaragoza":{"count":98},"Justo Sierra":{"count":118},"Nicolas Bravo":{"count":58},"Vicente Guerrero":{"count":159},"مدرسه":{"count":97},"ESCOLA":{"count":75},"sekolah":{"count":75},"École Primaire Publique":{"count":53},"Juan Escutia":{"count":122},"Josefa Ortiz De Dominguez":{"count":78},"Curso Comunitario":{"count":58},"Francisco I. Madero":{"count":52},"Francisco Villa":{"count":116},"Ignacio Allende":{"count":51},"Jose Clemente Orozco":{"count":59},"Lazaro Cardenas":{"count":69},"Miguel Hidalgo Y Costilla":{"count":213},"Ni�os Heroes":{"count":158},"Ricardo Flores Magon":{"count":91},"Valentin Gomez Farias":{"count":72},"Venustiano Carranza":{"count":64},"Jose Vasconcelos":{"count":75},"Lazaro Cardenas Del Rio":{"count":153},"Agustin Ya�ez":{"count":57},"Manuel Lopez Cotilla":{"count":111},"Nombre En Tramite":{"count":130},"Sor Juana Ines De La Cruz":{"count":56},"Francisco I Madero":{"count":87},"Jose Ma Morelos Y Pavon":{"count":120},"Pedro Moreno":{"count":69},"Ramon Corona":{"count":54},"Cursos Comunitarios":{"count":116},"Primaria Comunitaria":{"count":58},"Saint Kizito Primary School":{"count":61}},"cinema":{"Odeon":{"count":77},"Cineworld":{"count":58},"Cinemark":{"count":68}},"doctors":{"Ärztehaus":{"count":243},"Centro de Salud":{"count":89},"Поликлиника":{"count":152},"Cabinet Médical":{"count":77},"Orvosi rendelő":{"count":64},"Cabinet médical":{"count":84},"Инвитро":{"count":74},"Женская консультация":{"count":66},"Детская поликлиника":{"count":89},"Амбулатория":{"count":53},"Фельдшерско-акушерский пункт":{"count":58},"Ośrodek Zdrowia":{"count":58},"Медпункт":{"count":65},"ФАП":{"count":87},"Consultorio Médico":{"count":102},"Centre de Santé":{"count":54}},"hospital":{"Детская поликлиника":{"count":181},"Centro de Saúde":{"count":86},"Женская консультация":{"count":55},"Centro de Salud":{"count":280},"Cruz Roja":{"count":79},"IMSS":{"count":62},"Government Hospital":{"count":77},"ЦРБ":{"count":114},"Больница":{"count":276},"Поликлиника":{"count":325},"Центральная районная больница":{"count":133},"Роддом":{"count":106},"Городская больница":{"count":60},"Hospital":{"count":157},"Кожно-венерологический диспансер":{"count":51},"Hospital Municipal":{"count":102},"Hôpital":{"count":51},"경희한의원 (Gyeonghui Oriental Medicine Clinic)":{"count":52},"Амбулатория":{"count":81},"Скорая помощь":{"count":66},"Районная больница":{"count":74},"Медпункт":{"count":54},"Детская больница":{"count":87},"ФАП":{"count":86},"Родильный дом":{"count":66},"Инфекционное отделение":{"count":71},"Consultorio Médico":{"count":64},"โรงพยาบาลส่งเสริมสุขภาพตำบล":{"count":59}},"biergarten":{"Biergarten":{"count":86}},"theatre":{"Teatro Municipal":{"count":75},"Freilichtbühne":{"count":67},"Дом культуры":{"count":51},"Amphitheatre":{"count":77},"Anfiteatro":{"count":74},"Amphitheater":{"count":85},"Amfiteatr":{"count":79}},"bar":{"Bar Sport":{"count":81},"Bar Centrale":{"count":115},"Бар":{"count":53},"Beach Bar":{"count":55}},"car_wash":{"Spălătorie Auto":{"count":61},"Автомойка":{"count":1105},"Shell":{"count":150},"Statoil":{"count":58},"Мойка":{"count":106},"Car Wash":{"count":400},"Waschanlage":{"count":66},"Aral":{"count":86},"BP":{"count":61},"автомойка":{"count":60},"Intermarché":{"count":57},"Car wash":{"count":60},"Myjnia samochodowa":{"count":52},"Myjnia bezdotykowa":{"count":62},"H-E-B Car Wash":{"count":65}},"clinic":{"Детская поликлиника":{"count":130},"Centro de Salud":{"count":127},"Polyclinique":{"count":90},"Поликлиника":{"count":147},"Posto de Saúde":{"count":64},"Clinic":{"count":83},"Health Sub Center":{"count":71},"ФАП":{"count":138},"Aid Post":{"count":69}},"bicycle_rental":{"metropolradruhr":{"count":82},"Bicing":{"count":99}},"veterinary":{"Clinique vétérinaire":{"count":75},"Ветлечебница":{"count":55},"Vétérinaire":{"count":68},"Clinique Vétérinaire":{"count":106},"Ветеринарная клиника":{"count":60}},"dentist":{"Стоматология":{"count":437},"Zahnarzt":{"count":68},"Dentiste":{"count":61},"Clínica Dental":{"count":56},"Dental Clinic":{"count":55},"Dentist":{"count":85},"Aspen Dental":{"count":51},"Стоматологическая поликлиника":{"count":87},"Clinica Dental":{"count":212}},"casino":{"Casino":{"count":59}},"arts_centre":{"Дом культуры":{"count":159},"Клуб":{"count":55},"Świetlica wiejska":{"count":52}},"ice_cream":{"Grido":{"count":98}},"sauna":{"Баня":{"count":102}},"driving_school":{"Автошкола":{"count":92}},"social_facility":{"Социальный участковый":{"count":208},"Safe Haven":{"count":92}}},"shop":{"mobile_phone":{"Vodafone":{"count":827},"T-Punkt":{"count":53},"Билайн":{"count":318},"ソフトバンクショップ":{"count":463},"O2":{"count":433},"Carphone Warehouse":{"count":260},"Orange":{"count":565},"3 Store":{"count":64},"T-Mobile":{"count":477},"Sprint":{"count":269},"AT&T":{"count":380},"Verizon Wireless":{"count":453},"Verizon":{"count":94},"mobilcom debitel":{"count":56},"Евросеть":{"count":821},"Movistar":{"count":257},"Telekom Shop":{"count":80},"EE":{"count":143},"Telekom":{"count":111},"ドコモショップ":{"count":370},"Telus":{"count":51},"Claro":{"count":326},"Cricket":{"count":77},"The Phone House":{"count":120},"vodafone":{"count":59},"Bell":{"count":123},"SFR":{"count":133},"МТС":{"count":731},"Metro PCS":{"count":55},"Digicel":{"count":127},"Связной":{"count":695},"Мегафон":{"count":457},"Теле2":{"count":58},"Wind":{"count":115},"Boost Mobile":{"count":91},"Алло":{"count":52},"МегаФон":{"count":76},"MetroPCS":{"count":65},"Play":{"count":103},"Telenor":{"count":79},"au":{"count":107},"Plus":{"count":73},"Tele2":{"count":90},"auショップ":{"count":318},"Bitė":{"count":68}},"supermarket":{"Eurospar":{"count":329},"Merkur":{"count":117},"Sainsbury's":{"count":580},"Lidl":{"count":8439},"Edeka":{"count":2195},"Coles":{"count":525},"Iceland":{"count":468},"Woolworths":{"count":754},"denn's Biomarkt":{"count":119},"Billa":{"count":1507},"ALDI":{"count":5976},"The Co-operative Food":{"count":1146},"Checkers":{"count":134},"Penny":{"count":1836},"Norma":{"count":1128},"NETTO":{"count":4439},"Morrisons":{"count":447},"Kaufland":{"count":1119},"Tesco Metro":{"count":148},"Intermarché Contact":{"count":97},"Nahkauf":{"count":198},"Rewe":{"count":2766},"Aldi Süd":{"count":720},"Real":{"count":195},"Tesco Express":{"count":504},"King Soopers":{"count":96},"Kiwi":{"count":219},"Asda":{"count":234},"Pick n Pay":{"count":258},"Coop":{"count":2227},"Tengelmann":{"count":189},"Carrefour":{"count":2267},"Waitrose":{"count":288},"Spar":{"count":2996},"Hofer":{"count":461},"Tesco":{"count":1371},"M-Preis":{"count":80},"tegut":{"count":213},"Sainsbury's Local":{"count":200},"E-Center":{"count":66},"Aldi Nord":{"count":260},"Meijer":{"count":112},"Safeway":{"count":553},"No Frills":{"count":163},"Budgens":{"count":81},"Albert":{"count":245},"Jumbo":{"count":421},"Interspar":{"count":112},"Shoprite":{"count":294},"MPreis":{"count":70},"Penny Market":{"count":543},"Tesco Extra":{"count":186},"Albert Heijn":{"count":697},"IGA":{"count":488},"Super U":{"count":577},"Metro":{"count":333},"Migros":{"count":586},"Marktkauf":{"count":118},"Combi":{"count":121},"ICA":{"count":176},"PLUS":{"count":100},"Hoogvliet":{"count":60},"EMTÉ":{"count":66},"coop":{"count":80},"Dirk van den Broek":{"count":52},"Food Basics":{"count":108},"Casino":{"count":332},"Penny Markt":{"count":482},"Giant":{"count":243},"COOP Jednota":{"count":136},"ADEG":{"count":77},"ALDI SÜD":{"count":130},"Simply Market":{"count":483},"Konzum":{"count":321},"Carrefour Express":{"count":634},"Foodland":{"count":170},"Famila":{"count":152},"Hemköp":{"count":83},"Markant":{"count":91},"Volg":{"count":200},"Netto Marken-Discount":{"count":525},"Leader Price":{"count":417},"Treff 3000":{"count":120},"Kaiser's":{"count":231},"K+K":{"count":108},"Unimarkt":{"count":97},"Meny":{"count":79},"U Express":{"count":88},"Carrefour City":{"count":268},"Bim":{"count":468},"real,-":{"count":78},"Countdown":{"count":130},"Sobeys":{"count":158},"Cargills Food City":{"count":71},"S-Market":{"count":110},"Denner":{"count":376},"Zielpunkt":{"count":76},"NP":{"count":178},"Franprix":{"count":371},"Monoprix":{"count":271},"Landi":{"count":51},"Diska":{"count":66},"PENNY":{"count":86},"Giant Eagle":{"count":118},"NORMA":{"count":133},"NP-Markt":{"count":77},"Coop Extra":{"count":72},"AD Delhaize":{"count":75},"Grocery Outlet":{"count":79},"Auchan":{"count":215},"Mercadona":{"count":1050},"Consum":{"count":169},"Pam":{"count":73},"sky":{"count":118},"Şok":{"count":114},"Despar":{"count":194},"Eroski":{"count":269},"Costcutter":{"count":88},"SuperValu":{"count":73},"Dia":{"count":1198},"Rema 1000":{"count":437},"Bunnpris":{"count":69},"Konsum":{"count":140},"Profi":{"count":176},"Colruyt":{"count":203},"The Co-operative":{"count":67},"Rimi":{"count":112},"Delhaize":{"count":224},"CBA":{"count":241},"Real Canadian Superstore":{"count":59},"Mercator":{"count":155},"Smith's":{"count":53},"Walmart":{"count":999},"Kroger":{"count":550},"Intermarché":{"count":1559},"Albertsons":{"count":304},"Trader Joe's":{"count":324},"Feneberg":{"count":64},"Kvickly":{"count":54},"Makro":{"count":188},"Лента":{"count":104},"Nah & Frisch":{"count":100},"ALDI Nord":{"count":83},"Maxi":{"count":154},"Ашан":{"count":65},"CRAI":{"count":56},"ICA Supermarket":{"count":83},"Fakta":{"count":274},"Ekom":{"count":61},"Магнит":{"count":3327},"nahkauf":{"count":103},"Caprabo":{"count":129},"Famiglia Cooperativa":{"count":84},"Народная 7Я семьЯ":{"count":194},"Carrefour Contact":{"count":185},"Авоська":{"count":55},"Maxima XX":{"count":60},"Petit Casino":{"count":142},"Wasgau":{"count":55},"Match":{"count":133},"Pingo Doce":{"count":281},"Lider":{"count":69},"Unimarc":{"count":217},"Santa Isabel":{"count":155},"Седьмой континент":{"count":87},"Carrefour express":{"count":70},"HIT":{"count":60},"Пятёрочка":{"count":2392},"Conad":{"count":449},"Фуршет":{"count":82},"Willys":{"count":89},"Farmfoods":{"count":114},"Фора":{"count":126},"Dunnes Stores":{"count":74},"Сільпо":{"count":196},"マルエツ":{"count":87},"Alnatura":{"count":77},"Piggly Wiggly":{"count":87},"Prix":{"count":51},"Crai":{"count":99},"Biocoop":{"count":105},"REWE City":{"count":60},"El Árbol":{"count":103},"E. Leclerc":{"count":55},"Super Brugsen":{"count":69},"Дикси":{"count":1323},"Whole Foods Market":{"count":328,"tags":{"shop":"supermarket"}},"G20":{"count":65},"Eroski Center":{"count":63},"Publix":{"count":568},"Conad City":{"count":70},"Перекресток":{"count":409},"Føtex":{"count":67},"イトーヨーカドー":{"count":64},"Sprouts Farmers Market":{"count":55},"Ralphs":{"count":75},"Mila":{"count":73},"Biedronka":{"count":2155},"Proxi":{"count":55},"Eurospin":{"count":273},"Семья":{"count":76},"Виват":{"count":60},"Froiz":{"count":72},"Gadis":{"count":107},"Евроопт":{"count":168},"Квартал":{"count":74},"Esselunga":{"count":105},"SuperBrugsen":{"count":72},"Reliance Fresh":{"count":80},"Winn-Dixie":{"count":67},"Coop Jednota":{"count":97},"Irma":{"count":70},"Londis":{"count":54},"Mega Image":{"count":88},"Centre Commercial E. Leclerc":{"count":486},"西友":{"count":124},"A101":{"count":193},"Game":{"count":55},"Coop Konsum":{"count":97},"Alimerka":{"count":94},"Piotr i Paweł":{"count":98},"A&O":{"count":61},"Coviran":{"count":87},"Żabka":{"count":61},"Maxima":{"count":106},"ΑΒ Βασιλόπουλος":{"count":62},"Stokrotka":{"count":197},"Карусель":{"count":66},"Utile":{"count":52},"CONAD":{"count":64},"Winn Dixie":{"count":76},"Vival":{"count":67},"Μασούτης":{"count":64},"Mini Market":{"count":115},"イオン":{"count":84},"Chedraui":{"count":60},"Family Dollar":{"count":59},"Walmart Neighborhood Market":{"count":112},"Delikatesy Centrum":{"count":158},"Géant Casino":{"count":63},"Ekono":{"count":59},"ASDA":{"count":220},"Intermarche":{"count":117},"Stop & Shop":{"count":118},"Maxima X":{"count":147},"Tottus":{"count":58},"Food Lion":{"count":388},"Społem":{"count":99},"Harris Teeter":{"count":140},"Sam's Club":{"count":259},"Continente":{"count":96},"Foodworks":{"count":78},"Centra":{"count":60},"Maxi Dia":{"count":52},"H-E-B":{"count":271},"Price Chopper":{"count":123},"Soriana":{"count":148},"Атак":{"count":80},"Puregold":{"count":58},"Полушка":{"count":198},"Jewel-Osco":{"count":53},"Condis":{"count":103},"Big C":{"count":53},"Sigma":{"count":95},"Верный":{"count":160},"いなげや":{"count":57},"АТБ":{"count":499},"Bodega Aurrera":{"count":167},"Fresh Market":{"count":75},"Виктория":{"count":64},"Азбука Вкуса":{"count":52},"QFC":{"count":55},"Vea":{"count":62},"Minipreço":{"count":204},"Lewiatan":{"count":208},"Sisa":{"count":51},"Монетка":{"count":291},"Магнолия":{"count":111},"POLOmarket":{"count":186},"Palí":{"count":64},"Costco":{"count":264},"Tesco Lotus":{"count":90},"Lupa":{"count":69},"Hy-Vee":{"count":110},"Копейка":{"count":54},"Disco":{"count":68},"Pão de Açúcar":{"count":59},"Save-A-Lot":{"count":79,"tags":{"shop":"supermarket"}},"Walmart Supercenter":{"count":511},"Comercial Mexicana":{"count":53},"Plodine":{"count":61},"Grand Frais":{"count":52},"Hannaford":{"count":87},"Fred Meyer":{"count":76},"Мария-Ра":{"count":118},"マックスバリュ":{"count":109},"Wegmans":{"count":88},"Dia %":{"count":136},"Dollar General":{"count":92},"Cub Foods":{"count":51},"Универсам":{"count":84},"Extra":{"count":126},"Магазин":{"count":130},"ライフ":{"count":117},"Picard":{"count":93},"Гроздь":{"count":52},"Супермаркет":{"count":52},"Atacadão":{"count":63},"New World":{"count":86},"Ahorramás":{"count":56},"Eko":{"count":64},"Oxxo":{"count":112},"業務スーパー":{"count":129},"Despensa Familiar":{"count":68},"Красный Яр":{"count":60},"全聯福利中心":{"count":157},"Plaza Vea":{"count":53},"Командор":{"count":66},"Таврія-В":{"count":56},"まいばすけっと":{"count":108},"Norfa XL":{"count":63},"Indomaret":{"count":123},"Радеж":{"count":58},"Mercado de Abastos":{"count":52},"Dino":{"count":182},"Покупочка":{"count":51},"Хүнсний дэлгүүр":{"count":64},"E. Leclerc Drive":{"count":55},"Leclerc Drive":{"count":127},"Alfamart":{"count":76},"全聯":{"count":62}},"sports":{"Sports Direct":{"count":160},"Decathlon":{"count":388},"Intersport":{"count":614},"Спорттовары":{"count":60},"Nike":{"count":57},"Sports Authority":{"count":147},"Спортмастер":{"count":165},"Hervis":{"count":55},"Sport 2000":{"count":147},"Big 5 Sporting Goods":{"count":68},"Adidas":{"count":90},"Dick's Sporting Goods":{"count":170}},"department_store":{"Big W":{"count":114},"Canadian Tire":{"count":150},"Karstadt":{"count":64},"Walmart":{"count":802},"Kmart":{"count":359},"El Corte Inglés":{"count":60},"Target":{"count":947},"Big Lots":{"count":86},"The Warehouse":{"count":56},"Galeria Kaufhof":{"count":61},"Dollar General":{"count":53},"Debenhams":{"count":110},"Marks & Spencer":{"count":115},"Argos":{"count":71},"Woolworth":{"count":112},"Универмаг":{"count":139},"Sears":{"count":384},"Walmart Supercenter":{"count":195},"BHS":{"count":81},"Kohl's":{"count":302},"Bed Bath & Beyond":{"count":58},"Dillard's":{"count":60},"Macy's":{"count":243},"JCPenney":{"count":214},"Dollar Tree":{"count":59},"HEMA":{"count":157},"Family Dollar":{"count":65},"Sam's Club":{"count":95},"Магнит":{"count":87}},"convenience":{"Shell":{"count":412},"Statoil":{"count":78},"Spar":{"count":1340},"Tesco Express":{"count":605},"Sainsbury's Local":{"count":192},"Aral":{"count":84},"One Stop":{"count":233},"The Co-operative Food":{"count":318},"Londis":{"count":453},"7-Eleven":{"count":8603},"Coop":{"count":1110},"Sale":{"count":86},"Sheetz":{"count":111},"Costcutter":{"count":379},"Konzum":{"count":219},"Siwa":{"count":222},"Esso":{"count":120},"COOP Jednota":{"count":324},"Mac's":{"count":254},"Alepa":{"count":68},"Hasty Market":{"count":84},"K-Market":{"count":64},"On the Run":{"count":106},"CBA":{"count":291},"Valintatalo":{"count":55},"Alimentación":{"count":88},"Casino":{"count":89},"Franprix":{"count":85},"Circle K":{"count":603},"セブンイレブン":{"count":6433,"tags":{"name:en":"7-Eleven"}},"ローソン":{"count":3335,"tags":{"name:en":"LAWSON"}},"BP":{"count":238},"Tesco":{"count":59},"OK":{"count":72},"Migrolino":{"count":66},"Petit Casino":{"count":285},"Volg":{"count":147},"Total":{"count":51},"Coop Pronto":{"count":53},"Mace":{"count":142},"Mini Market":{"count":874},"Kiosk":{"count":455},"Nisa Local":{"count":114},"Продукты":{"count":7552},"Mini Stop":{"count":362},"LAWSON":{"count":265},"デイリーヤマザキ":{"count":314},"Biedronka":{"count":96},"Надежда":{"count":94},"Mobil":{"count":78},"Nisa":{"count":67},"Premier":{"count":224},"ABC":{"count":655},"КазМунайГаз":{"count":120},"McColl's":{"count":159},"Carrefour Express":{"count":178},"ミニストップ":{"count":631,"tags":{"name:en":"MINISTOP"}},"サンクス":{"count":893,"tags":{"name:en":"sunkus"}},"スリーエフ":{"count":221},"8 à Huit":{"count":76},"Żabka":{"count":1199},"Almacen":{"count":375},"Mercator":{"count":109},"Proxi":{"count":199},"萊爾富":{"count":298},"全家便利商店":{"count":524},"Vival":{"count":309},"FamilyMart":{"count":742},"ファミリーマート":{"count":3307,"tags":{"name:en":"FamilyMart"}},"Магазин":{"count":1407},"Carrefour City":{"count":88},"Casey's General Store":{"count":174},"セブンイレブン(Seven-Eleven)":{"count":246},"Jednota":{"count":67},"Гастроном":{"count":321},"Centra":{"count":130},"Евроопт":{"count":104},"Couche-Tard":{"count":71},"サークルK":{"count":976,"tags":{"name:en":"Circle K"}},"7 eleven":{"count":71},"Mlin i pekare":{"count":59},"Sunkus":{"count":54},"Wawa":{"count":228},"Lifestyle Express":{"count":75},"Chevron":{"count":89},"ampm":{"count":132},"General Store":{"count":75},"Tchibo":{"count":65},"Lewiatan":{"count":397},"Coles Express":{"count":170},"Večerka":{"count":110},"Potraviny":{"count":393},"Rite Aid":{"count":59},"Select":{"count":111},"Ассорти":{"count":85},"Копейка":{"count":55},"Универсам":{"count":118},"Берёзка":{"count":170},"Русь":{"count":52},"Społem":{"count":161},"Shop":{"count":473},"Cumberland Farms":{"count":96},"Fresh Market":{"count":75},"Мария-Ра":{"count":189},"Пятёрочка":{"count":671},"Woolworths Petrol":{"count":73},"Aibė":{"count":71},"Coop Jednota":{"count":120},"Магнит":{"count":1196},"Tesco Lotus Express":{"count":89},"Смак":{"count":104},"Виктория":{"count":122},"Plaid Pantry":{"count":60},"M&S Simply Food":{"count":56},"Sklep spożywczy":{"count":223},"Groszek":{"count":187},"Продукти":{"count":595},"Martin's":{"count":51},"Bodega":{"count":55},"Татьяна":{"count":55},"24 часа":{"count":76},"Минимаркет":{"count":279},"Oxxo":{"count":1566},"abc":{"count":237},"Family Dollar":{"count":60},"Stewart's":{"count":253},"Любимый":{"count":67},"Shop & Go":{"count":72},"Hruška":{"count":76},"ローソンストア100":{"count":252},"CU":{"count":57},"Гурман":{"count":57},"Sunoco":{"count":54},"Радуга":{"count":131},"Delikatesy Centrum":{"count":142},"Фортуна":{"count":80},"Магнолия":{"count":79},"Magazin Mixt":{"count":98},"Kum & Go":{"count":102},"Magazin Alimentar":{"count":60},"Маяк":{"count":58},"Prehrana":{"count":87},"Picard":{"count":95},"Epicerie":{"count":398},"Эконом":{"count":60},"Four Square":{"count":84},"Визит":{"count":84},"Nasz Sklep":{"count":64},"Апельсин":{"count":53},"Авоська":{"count":92},"Dollar General":{"count":397},"Studenac":{"count":107},"Magazin":{"count":61},"Central Convenience Store":{"count":66},"セイコーマート":{"count":258},"Mini Mart":{"count":62},"Mini ABC":{"count":66},"Holiday":{"count":65},"Тройка":{"count":56},"продукты":{"count":139},"Теремок":{"count":91},"Alimentari":{"count":72},"Кулинария":{"count":105},"Агрокомплекс":{"count":51},"Speedway":{"count":85},"全家":{"count":414},"Citgo":{"count":73},"GS25":{"count":89},"Extra":{"count":63},"Kwik Trip":{"count":116},"Мечта":{"count":81},"Кировский":{"count":78},"United Dairy Farmers":{"count":52},"Freshmarket":{"count":87},"Mini market":{"count":66},"Перекресток":{"count":118},"Delikatesy":{"count":127},"Odido":{"count":74},"Corner Store":{"count":74},"Монетка":{"count":118},"Ромашка":{"count":63},"Alimentation Générale":{"count":73},"ポプラ":{"count":95},"BP Shop":{"count":57},"Верный":{"count":52},"Дикси":{"count":246},"Продуктовый":{"count":227},"Almacén":{"count":73},"Весна":{"count":78},"Центральный":{"count":58},"Мираж":{"count":51},"Mini Market Non-Stop":{"count":124},"ココストア":{"count":53},"Светлана":{"count":72},"Копеечка":{"count":83},"QuikTrip":{"count":133},"Меркурий":{"count":63},"Food Mart":{"count":384},"Royal Farms":{"count":75},"Vegyesbolt":{"count":326},"Елена":{"count":51},"Продукты 24":{"count":61},"Kisbolt":{"count":98},"Parduotuvė":{"count":67},"Reál":{"count":52},"AMPM":{"count":114},"ヤマザキショップ":{"count":86},"Продуктовый магазин":{"count":611},"Alfamart":{"count":228},"odido":{"count":53},"Indomaret":{"count":275},"магазин":{"count":258},"Alfa Mart":{"count":55},"Fresh":{"count":57},"Boutique":{"count":163},"მარკეტი (Market)":{"count":140},"Magazin alimentar":{"count":52},"OK便利商店":{"count":65},"Magazin Non-Stop":{"count":64},"Sari-sari Store":{"count":65},"Stores":{"count":66},"Małpka Express":{"count":56},"Baqala":{"count":61}},"chemist":{"Budnikowsky":{"count":102},"dm":{"count":1667},"Müller":{"count":321},"Schlecker":{"count":97},"Etos":{"count":480},"Bipa":{"count":398},"Rossmann":{"count":2241},"Teta":{"count":82},"Kruidvat":{"count":338},"Walgreens":{"count":57},"Рубль Бум":{"count":64},"Watsons":{"count":87},"Улыбка радуги":{"count":96},"7 Дней":{"count":52},"Бытовая химия":{"count":67},"丁丁藥局":{"count":72},"Магнит Косметик":{"count":53},"屈臣氏":{"count":56}},"car_repair":{"Peugeot":{"count":133},"Kwik Fit":{"count":215},"A.T.U":{"count":460},"Midas":{"count":387},"Feu Vert":{"count":152},"Norauto":{"count":220},"Шиномонтаж":{"count":2787},"Speedy":{"count":175},"Автозапчасти":{"count":209},"Renault":{"count":257},"Pit Stop":{"count":72},"Garage Renault":{"count":57},"Jiffy Lube":{"count":363},"СТО":{"count":820},"Автосервис":{"count":668},"O'Reilly Auto Parts":{"count":194},"Pep Boys":{"count":68},"Carglass":{"count":181},"ÖAMTC":{"count":53},"шиномонтаж":{"count":136},"Citroen":{"count":93},"Euromaster":{"count":133},"NAPA Auto Parts":{"count":83},"Mr. Lube":{"count":52},"Valvoline Instant Oil Change":{"count":74},"Wulkanizacja":{"count":64},"Firestone":{"count":176},"Goodyear":{"count":75},"Roady":{"count":75},"Mekonomen":{"count":51},"Автомастерская":{"count":74},"Advance Auto Parts":{"count":238},"Замена масла":{"count":74},"Gomeria":{"count":110},"Firestone Complete Auto Care":{"count":52},"Автосервис+шиномонтаж":{"count":55},"Gomería":{"count":65}},"bakery":{"Red Ribbon":{"count":53},"Kamps":{"count":263},"Lila Bäcker":{"count":83},"Bäckerei Schmidt":{"count":95},"Anker":{"count":83},"Schäfer":{"count":59},"Schäfer's":{"count":80},"Sternenbäck":{"count":74},"Hofpfisterei":{"count":125},"Bakers Delight":{"count":62},"Greggs":{"count":481},"Panaderia":{"count":367},"Ströck":{"count":62},"Oebel":{"count":65},"Sehne":{"count":76},"Boulangerie":{"count":454},"Stadtbäckerei":{"count":60},"Banette":{"count":89},"Steinecke":{"count":234},"Goldilocks":{"count":106},"Backwerk":{"count":130},"Dat Backhus":{"count":77},"K&U":{"count":98},"Ihle":{"count":100},"Der Beck":{"count":102},"Ditsch":{"count":60},"Bäckerei Fuchs":{"count":59},"Bakker Bart":{"count":80},"Bäckerei Müller":{"count":66},"Backshop":{"count":51},"Wiener Feinbäcker":{"count":58},"Bäckerei Grimminger":{"count":52},"Goeken backen":{"count":53},"von Allwörden":{"count":52},"Paul":{"count":150},"Musmanni":{"count":73},"Хлеб":{"count":136},"Fornetti":{"count":110},"Le Fournil":{"count":51},"Булочная":{"count":56},"boulangerie":{"count":65},"Пекарня":{"count":187},"Mlinar":{"count":71},"Свежий хлеб":{"count":59},"Marie Blachère":{"count":53},"Cooplands":{"count":57},"Кулиничи":{"count":101}},"furniture":{"IKEA":{"count":215},"Dänisches Bettenlager":{"count":424},"Jysk":{"count":209},"Roller":{"count":89},"Conforama":{"count":141},"The Brick":{"count":51},"Мебель":{"count":327},"Casa":{"count":57},"JYSK":{"count":97},"But":{"count":115},"Pier 1 Imports":{"count":81},"ニトリ":{"count":68},"Black Red White":{"count":61}},"doityourself":{"Hornbach":{"count":129},"B&Q":{"count":235},"Hubo":{"count":93},"Mr Bricolage":{"count":133},"Gamma":{"count":122},"OBI":{"count":498},"Lowe's":{"count":1228},"Wickes":{"count":148},"Hagebau":{"count":53},"Castorama":{"count":161},"Rona":{"count":69},"Toom Baumarkt":{"count":95},"Homebase":{"count":209},"Lagerhaus":{"count":108},"Bauhaus":{"count":210},"Leroy Merlin":{"count":255},"Hellweg":{"count":65},"Brico":{"count":125},"Bricomarché":{"count":381},"Hagebaumarkt":{"count":128},"Biltema":{"count":52},"BayWa":{"count":53},"Home Depot":{"count":1250},"Menards":{"count":103},"Weldom":{"count":101},"Toom":{"count":63},"Praktiker":{"count":62},"Canadian Tire":{"count":125},"Easy":{"count":51},"Sonderpreis Baumarkt":{"count":52},"Ace Hardware":{"count":246},"Screwfix":{"count":62},"Karwei":{"count":59},"Mr. Bricolage":{"count":56},"Строитель":{"count":57},"Home Hardware":{"count":144},"Мастер":{"count":53},"Хозтовары":{"count":128},"コメリ":{"count":108},"Bunnings Warehouse":{"count":167},"Bricorama":{"count":103},"Стройматериалы":{"count":401},"コーナン":{"count":67},"Point P":{"count":102}},"stationery":{"Staples":{"count":580},"McPaper":{"count":136},"Ryman":{"count":74},"Pagro":{"count":64},"Officeworks":{"count":59},"Office Depot":{"count":295},"Libro":{"count":64},"Office Max":{"count":138},"Канцтовары":{"count":110}},"car":{"Skoda":{"count":122},"BMW":{"count":189},"KIA":{"count":74},"Citroen":{"count":395},"Renault":{"count":560},"Mercedes-Benz":{"count":335},"Volvo":{"count":146},"Ford":{"count":382},"Kia Motors":{"count":97},"Mazda":{"count":164},"Mitsubishi":{"count":120},"Fiat":{"count":130},"Автозапчасти":{"count":243},"Opel":{"count":206},"Volkswagen":{"count":318},"Toyota":{"count":467},"Nissan":{"count":330},"Seat":{"count":84},"Porsche":{"count":72},"Suzuki":{"count":127},"Honda":{"count":271},"Peugeot":{"count":461},"Lexus":{"count":66},"KIA Motors":{"count":54},"Hyundai":{"count":330},"Kia":{"count":108},"Audi":{"count":158},"Автомагазин":{"count":92},"Subaru":{"count":92},"Chevrolet":{"count":178}},"kiosk":{"Shell":{"count":119},"R-kioski":{"count":147},"Aral":{"count":73},"Kiosk":{"count":774},"R-Kioski":{"count":198},"Narvesen":{"count":177},"Tabak Trafik":{"count":65},"Trafik":{"count":235},"Pressbyrån":{"count":104},"Trinkhalle":{"count":96},"Relay":{"count":54},"Kiosco":{"count":164},"Edicola":{"count":68},"Пресса":{"count":130},"Trafika":{"count":64},"Роспечать":{"count":218},"Ruch":{"count":146},"Продукты":{"count":216},"Tisak":{"count":218},"Киоск":{"count":137},"Kolporter":{"count":70},"Мороженое":{"count":55},"Kiosko":{"count":63},"Kios":{"count":191},"Lietuvos spauda":{"count":59},"Союзпечать":{"count":87},"Pulpería":{"count":59},"მარკეტი (Market)":{"count":138},"KIOS":{"count":84},"Warung":{"count":68}},"electronics":{"Maplin":{"count":102},"Media Markt":{"count":378},"Saturn":{"count":147},"Currys":{"count":116},"Euronics":{"count":203},"Rogers":{"count":59},"Radio Shack":{"count":461},"Apple Store":{"count":56},"Best Buy":{"count":609},"Elgiganten":{"count":52},"Expert":{"count":173},"Эльдорадо":{"count":265},"DNS":{"count":74},"Hartlauer":{"count":52},"Darty":{"count":130},"Interdiscount":{"count":52},"М.Видео":{"count":106},"Bell":{"count":76},"Samsung":{"count":99},"Фокстрот":{"count":70},"ケーズデンキ":{"count":111},"The Source":{"count":67},"Boulanger":{"count":65},"Batteries Plus Bulbs":{"count":67},"Эксперт":{"count":61},"Media Expert":{"count":119},"ヤマダ電機":{"count":129},"エディオン":{"count":62},"Neonet":{"count":73},"La Curacao":{"count":63}},"variety_store":{"Tedi":{"count":575},"Action":{"count":85},"Dollar Tree":{"count":487},"Dollarama":{"count":295},"ダイソー":{"count":152},"Fix Price":{"count":92},"Family Dollar":{"count":405},"GiFi":{"count":92},"Dollar General":{"count":233},"Big Lots":{"count":54},"Poundland":{"count":132},"Variety Store":{"count":143}},"alcohol":{"Alko":{"count":169},"Beer Store":{"count":54},"LCBO":{"count":371},"The Beer Store":{"count":213},"Systembolaget":{"count":259},"Норман":{"count":120},"Ароматный мир":{"count":130},"Bargain Booze":{"count":108},"BWS":{"count":124},"Vinmonopolet":{"count":60},"Botilleria":{"count":87},"SAQ":{"count":118},"Gall & Gall":{"count":505},"Liquorland":{"count":86},"Mitra":{"count":60},"Nicolas":{"count":180},"Живое пиво":{"count":158},"Dan Murphy's":{"count":54},"Красное и белое":{"count":88},"BC Liquor Store":{"count":52},"Красное & Белое":{"count":168},"Liquor Store":{"count":54},"Бристоль":{"count":152},"Красное и Белое":{"count":57},"Разливное пиво":{"count":96},"Красное&Белое":{"count":78},"Пиво":{"count":53}},"bicycle":{"Halfords":{"count":156},"サイクルベースあさひ":{"count":64},"Веломарка":{"count":52}},"clothes":{"KiK":{"count":1684},"H&M":{"count":1182},"C&A":{"count":764},"Second Hand":{"count":129},"Urban Outfitters":{"count":107},"Vögele":{"count":182},"Zeeman":{"count":272},"Takko":{"count":761},"Adler":{"count":75},"Charles Vögele":{"count":114},"Nike":{"count":80},"Peek & Cloppenburg":{"count":68},"OVS":{"count":59},"Zara":{"count":413},"Vero Moda":{"count":187},"Ernsting's family":{"count":631},"Winners":{"count":93},"NKD":{"count":690},"GAP":{"count":63},"River Island":{"count":105},"Next":{"count":262},"Monsoon":{"count":72},"Gap":{"count":147},"Adidas":{"count":176},"Gerry Weber":{"count":183},"Woolworths":{"count":119},"Ulla Popken":{"count":105},"Mr Price":{"count":93},"Jet":{"count":65},"Pep":{"count":134},"Edgars":{"count":113},"Ackermans":{"count":93},"House":{"count":53},"Truworths":{"count":66},"Reserved":{"count":99},"Ross":{"count":215},"Hugo Boss":{"count":82},"Burton":{"count":78},"Dorothy Perkins":{"count":77},"s.Oliver":{"count":89},"Cecil":{"count":103},"Lane Bryant":{"count":66},"Dress Barn":{"count":97},"Old Navy":{"count":303},"Dressmann":{"count":56},"Jack & Jones":{"count":142},"Hunkemöller":{"count":129},"Pimkie":{"count":141},"Esprit":{"count":359},"Primark":{"count":150},"Bonita":{"count":277},"Mexx":{"count":76},"Matalan":{"count":127},"Tally Weijl":{"count":118},"Mango":{"count":277},"TK Maxx":{"count":157},"Springfield":{"count":69},"Sisley":{"count":68},"Benetton":{"count":164},"AWG":{"count":83},"Tommy Hilfiger":{"count":149},"Wibra":{"count":59},"Fat Face":{"count":72},"Reitmans":{"count":51},"Lindex":{"count":99},"New Look":{"count":230},"KappAhl":{"count":64},"New Yorker":{"count":301},"Etam":{"count":91},"Kiabi":{"count":234},"Palmers":{"count":68},"Jack Wolfskin":{"count":69},"American Apparel":{"count":86},"Desigual":{"count":135},"Cubus":{"count":54},"Gant":{"count":65},"Tom Tailor":{"count":101},"Topshop":{"count":58},"Bershka":{"count":117},"Burlington Coat Factory":{"count":76},"Jules":{"count":95},"Guess":{"count":100},"Jennyfer":{"count":60},"Pepco":{"count":88},"Orsay":{"count":139},"Tezenis":{"count":64},"Forever 21":{"count":84},"Mark's":{"count":55},"Triumph":{"count":100},"Timberland":{"count":66},"Superdry":{"count":62},"AOKI":{"count":89},"Calzedonia":{"count":186},"Intimissimi":{"count":119},"Orchestra":{"count":79},"United Colors of Benetton":{"count":159},"Goodwill":{"count":56},"洋服の青山":{"count":199},"Levi's":{"count":152},"Petit Bateau":{"count":55},"Diesel":{"count":66},"American Eagle Outfitters":{"count":62},"Celio":{"count":140},"Camaïeu":{"count":98},"Puma":{"count":55},"Lacoste":{"count":156},"WE":{"count":62},"Men's Wearhouse":{"count":112},"Sergent Major":{"count":63},"Jeans Fritz":{"count":92},"Ross Dress for Less":{"count":52},"Promod":{"count":159},"Street One":{"count":129},"TJ Maxx":{"count":171},"ユニクロ":{"count":168},"Engbers":{"count":62},"Only":{"count":62},"Marc O'Polo":{"count":61},"Banana Republic":{"count":102},"Одежда":{"count":124},"Marshalls":{"count":161},"La Halle":{"count":113},"Peacocks":{"count":144},"Camaieu":{"count":68},"Justice":{"count":59},"Massimo Dutti":{"count":76},"Cache Cache":{"count":53},"Женская одежда":{"count":51},"Victoria's Secret":{"count":90},"Спецодежда":{"count":65},"西松屋":{"count":84},"Calvin Klein":{"count":56},"Stradivarius":{"count":66},"Stefanel":{"count":51},"Gina Laura":{"count":57},"Chico's":{"count":74},"Caroll":{"count":61},"しまむら":{"count":161},"Gémo":{"count":71},"ワークマン":{"count":51},"Mim":{"count":52},"Cropp":{"count":52},"Toko Pakaian":{"count":72}},"bookmaker":{"Paddy Power":{"count":102},"Ladbrokes":{"count":497},"Betfred":{"count":229},"William Hill":{"count":518},"Coral":{"count":352}},"video_games":{"GameStop":{"count":372},"Game Stop":{"count":80},"EB Games":{"count":86},"Micromania":{"count":67},"Gamestop":{"count":56},"Game":{"count":53}},"beverages":{"REWE Getränkemarkt":{"count":131},"Getränke Hoffmann":{"count":164},"Orterer Getränkemarkt":{"count":65},"Rewe Getränkemarkt":{"count":110},"Getränkemarkt":{"count":104},"Fristo":{"count":85},"Trinkgut":{"count":58},"Dursty":{"count":71},"Getränkeland":{"count":71},"Edeka Getränkemarkt":{"count":62},"trinkgut":{"count":52}},"pet":{"Fressnapf":{"count":555},"PetSmart":{"count":398},"Pet Valu":{"count":84},"Das Futterhaus":{"count":128},"Pets at Home":{"count":133},"Petco":{"count":281},"Зоотовары":{"count":63}},"butcher":{"Boucherie":{"count":103},"Carniceria":{"count":69},"Мясо":{"count":131},"Великолукский мясокомбинат":{"count":160},"Мясная лавка":{"count":165},"Macelleria":{"count":68},"Ариант":{"count":69},"Свежее мясо":{"count":82}},"tobacco":{"Estanco":{"count":76},"Tabacchi":{"count":53},"Табак":{"count":58},"Nemzeti Dohánybolt":{"count":386},"Nemzeti dohánybolt":{"count":134}},"laundry":{"Laundrette":{"count":52},"Coin Laundry":{"count":71},"Laverie":{"count":96},"Laundromat":{"count":122},"Lavanderia":{"count":76},"Laundry":{"count":84}},"optician":{"Boots Opticians":{"count":68},"Fielmann":{"count":375},"Pearle":{"count":120},"Apollo":{"count":377},"Hakim Optical":{"count":62},"メガネスーパー":{"count":51},"Vision Express":{"count":146},"Générale d'Optique":{"count":66},"Optic 2000":{"count":225},"Alain Afflelou":{"count":153},"Specsavers":{"count":287},"Krys":{"count":144},"Optical Center":{"count":90},"Atol":{"count":101},"Les Opticiens Mutualistes":{"count":76},"Hans Anders":{"count":63},"Optika":{"count":51},"眼鏡市場":{"count":176},"แว่นท็อปเจริญ":{"count":57}},"hardware":{"Lowe's":{"count":81},"1000 мелочей":{"count":87},"Стройматериалы":{"count":87},"Home Hardware":{"count":67},"Хозтовары":{"count":336},"Ferretería":{"count":78},"Hardware":{"count":63},"Quincaillerie":{"count":66},"Сантехника":{"count":52},"Ferreteria":{"count":95}},"shoes":{"Deichmann":{"count":1083},"Reno":{"count":231},"Payless ShoeSource":{"count":91},"Ecco":{"count":131},"Clarks":{"count":221},"La Halle aux Chaussures":{"count":120},"東京靴流通センター":{"count":56},"Brantano":{"count":130},"Tamaris":{"count":73},"Geox":{"count":113},"Salamander":{"count":88},"Payless Shoe Source":{"count":255},"Famous Footwear":{"count":132},"Quick Schuh":{"count":109},"Foot Locker":{"count":192},"Shoe Zone":{"count":135},"Siemes Schuhcenter":{"count":62},"Юничел":{"count":54},"Ремонт обуви":{"count":51},"Rieker":{"count":55},"Aldo":{"count":59},"Bata":{"count":200},"Eram":{"count":73},"CCC":{"count":169},"Scapino":{"count":55},"ЦентрОбувь":{"count":73},"Chaussea":{"count":74}},"toys":{"La Grande Récré":{"count":82},"Toys R Us":{"count":358,"tags":{"shop":"toys"}},"Intertoys":{"count":108},"Bart Smit":{"count":80},"Детский мир":{"count":151},"Maxi Toys":{"count":51},"Игрушки":{"count":76},"King Jouet":{"count":78},"Dráčik":{"count":51}},"travel_agency":{"Flight Centre":{"count":130},"Thomson":{"count":106},"Thomas Cook":{"count":236},"First Reisebüro":{"count":52},"TUI":{"count":187},"The Co-operative Travel":{"count":51}},"jewelry":{"585":{"count":77},"Bijou Brigitte":{"count":143},"Christ":{"count":98},"Claire's":{"count":69},"Swarovski":{"count":174},"Pandora":{"count":177},"Адамас":{"count":54},"Kay Jewelers":{"count":59}},"carpet":{"Carpet Right":{"count":90}},"energy":{"Punto Enel":{"count":1007}},"beauty":{"Yves Rocher":{"count":708},"Nails":{"count":60},"Sally Beauty Supply":{"count":101}},"car_parts":{"Halfords":{"count":84},"Автозапчасти":{"count":576},"Автомагазин":{"count":75},"AutoZone":{"count":481},"O'Reilly Auto Parts":{"count":222},"NAPA Auto Parts":{"count":185},"Advance Auto Parts":{"count":210},"タイヤ館":{"count":76},"Repco":{"count":58},"オートバックス":{"count":65},"イエローハット":{"count":57},"Tokić":{"count":61},"repuestos automotrices":{"count":61}},"video":{"World of Video":{"count":59},"Family Video":{"count":72},"Blockbuster":{"count":90},"TSUTAYA":{"count":94},"ゲオ":{"count":58}},"charity":{"British Heart Foundation":{"count":137},"Cancer Research UK":{"count":101},"Oxfam":{"count":169},"Scope":{"count":55},"Age UK":{"count":91},"Goodwill":{"count":77},"Sue Ryder":{"count":57}},"florist":{"Monceau Fleurs":{"count":62},"Blumenladen":{"count":69},"Interflora":{"count":66},"Blume 2000":{"count":86},"Цветы":{"count":1002},"Blumen":{"count":74},"Blumen Risse":{"count":64},"상록식물원 (Sangnok Florist)":{"count":57},"Florărie":{"count":53},"Kwiaciarnia":{"count":177},"Virágbolt":{"count":56}},"tailor":{"Änderungsschneiderei":{"count":171},"Ателье":{"count":70}},"hearing_aids":{"Kind Hörgeräte":{"count":61},"Amplifon":{"count":84}},"hairdresser":{"Klier":{"count":218},"Klipp":{"count":64},"Toni & Guy":{"count":63},"Haarscharf":{"count":56},"Supercuts":{"count":276},"Hairkiller":{"count":73},"Great Clips":{"count":426},"Парикмахерская":{"count":719},"Haarmonie":{"count":74},"Top Hair":{"count":64},"Figaro":{"count":60},"Перукарня":{"count":81},"Tchip":{"count":53},"Jean Louis David":{"count":76},"The Barber Shop":{"count":81},"Стиль":{"count":74},"Sport Clips":{"count":88},"Franck Provost":{"count":120},"Hair Cuttery":{"count":92},"Cost Cutters":{"count":56},"Coiffure":{"count":61},"Шарм":{"count":60},"Салон красоты":{"count":80},"Peluquería":{"count":58}},"bed":{"Matratzen Concord":{"count":324},"Dänisches Bettenlager":{"count":129},"Mattress Firm":{"count":102}},"copyshop":{"FedEx Office Print and Ship Center":{"count":166}},"erotic":{"Orion":{"count":76}},"money_lender":{"Money Mart":{"count":79}},"cosmetics":{"The Body Shop":{"count":59},"Yves Rocher":{"count":73},"Sephora":{"count":59},"Л'Этуаль":{"count":66}},"confectionery":{"Thorntons":{"count":57},"Hussel":{"count":71},"Leonidas":{"count":75},"Fagyizó":{"count":59}},"music":{"HMV":{"count":79}},"motorcycle":{"Harley Davidson":{"count":58},"Yamaha":{"count":171},"Honda":{"count":174},"Suzuki":{"count":80}},"newsagent":{"Relay":{"count":212},"WH Smith":{"count":53},"Maison de la Presse":{"count":103},"WHSmith":{"count":72},"Печать":{"count":92},"Tabac Presse":{"count":58},"Роспечать":{"count":306},"Союзпечать":{"count":120},"Edicola":{"count":94},"Витебскоблсоюзпечать":{"count":52},"Пресса":{"count":73}},"lottery":{"Lotto":{"count":113},"ONCE":{"count":68},"Lottózó":{"count":60}},"coffee":{"Tchibo":{"count":155},"Starbucks":{"count":164,"tags":{"cuisine":"coffee_shop"}},"Café Amazon":{"count":219}},"garden_centre":{"Dehner":{"count":56},"Jardiland":{"count":114},"Gamm Vert":{"count":164},"Point Vert":{"count":55}},"tyres":{"Шиномонтаж":{"count":349},"Discount Tire":{"count":67},"Euromaster":{"count":60},"Borracharia":{"count":55},"Вулканизация":{"count":67}},"baby_goods":{"Babies R Us":{"count":67}},"craft":{"Michael's":{"count":74},"Michaels":{"count":79},"Hobby Lobby":{"count":57}},"outdoor":{"REI":{"count":66},"Mountain Warehouse":{"count":59},"Рыболов":{"count":62}},"houseware":{"Blokker":{"count":212},"Xenos":{"count":67},"Marskramer":{"count":58}},"computer":{"PC World":{"count":63},"ДНС":{"count":51},"DNS":{"count":201},"Apple Store":{"count":70}},"interior_decoration":{"Depot":{"count":66}},"second_hand":{"Goodwill":{"count":171}},"pawnbroker":{"Cash Converters":{"count":64},"Ломбард":{"count":177}},"hifi":{},"farm":{"Hofladen":{"count":51}},"dry_cleaning":{"Химчистка":{"count":55},"Диана":{"count":68},"Cleaners":{"count":80},"ホワイト急便":{"count":81}},"paint":{"Sherwin-Williams":{"count":107},"Comex":{"count":51},"Sherwin Williams":{"count":111}},"funeral_directors":{"Ритуальные услуги":{"count":114},"The Co-operative Funeralcare":{"count":53}},"gift":{"Hallmark":{"count":119},"Сувениры":{"count":60},"Card Factory":{"count":70},"Gift Shop":{"count":53}},"ticket":{"Проездные билеты":{"count":54},"Boutique Grandes Lignes":{"count":63},"Guichet Transilien":{"count":245}},"greengrocer":{"Овощи-фрукты":{"count":98},"Zöldséges":{"count":52}},"ice_cream":{"Мороженое":{"count":67}},"fabric":{"Ткани":{"count":105}},"frame":{"rumah penduduk":{"count":175}},"kitchen":{"Home Utensils":{"count":65}}},"tourism":{"hotel":{"Holiday Inn":{"count":429},"Hotel Ibis":{"count":67},"Novotel":{"count":172},"Crowne Plaza":{"count":86},"Premier Inn":{"count":362},"Holiday Inn Express":{"count":472},"Park Hotel":{"count":75},"Krone":{"count":66},"Ibis":{"count":203},"Ibis Budget":{"count":178},"Travelodge":{"count":280},"City Hotel":{"count":69},"Hotel Royal":{"count":54},"Campanile":{"count":137},"Comfort Inn":{"count":273},"Quality Inn & Suites":{"count":57},"Courtyard by Marriott":{"count":74},"Mercure":{"count":112},"Hotel Europa":{"count":74},"Formule 1":{"count":70},"Grand Hotel":{"count":83},"Hilton":{"count":56},"Courtyard Marriott":{"count":69},"Hotel Krone":{"count":56},"Ramada":{"count":103},"Best Western":{"count":231},"Quality Inn":{"count":166},"Days Inn":{"count":246},"Royal Hotel":{"count":81},"Marriott":{"count":66},"Première Classe":{"count":53},"Hotel Central":{"count":78},"Hotel Victoria":{"count":52},"東横イン":{"count":53},"Kyriad":{"count":60},"Parkhotel":{"count":65},"Extended Stay America":{"count":90},"Hotel zur Post":{"count":57},"Fairfield Inn":{"count":60},"Hotel Post":{"count":56},"Staybridge Suites":{"count":51},"Hotel Panorama":{"count":51},"Hampton Inn & Suites":{"count":84},"Hotel":{"count":270},"Sheraton":{"count":65},"Hôtel Ibis":{"count":63},"Sleep Inn":{"count":59},"Country Inn & Suites":{"count":82},"Comfort Suites":{"count":143},"Super 8":{"count":223},"Гостиница":{"count":120},"Residence Inn":{"count":83},"Homewood Suites":{"count":57},"Hilton Garden Inn":{"count":178},"Hôtel de France":{"count":53},"Hampton Inn":{"count":380},"Embassy Suites":{"count":65},"Econo Lodge":{"count":66},"Comfort Inn & Suites":{"count":59},"Motel 6":{"count":85},"La Quinta":{"count":57},"Holiday Inn Express & Suites":{"count":56},"Fairfield Inn & Suites":{"count":63}},"motel":{"Travelodge":{"count":68},"Motel":{"count":72},"Econo Lodge":{"count":81},"Super 8":{"count":162},"Days Inn":{"count":100},"Motel 6":{"count":190},"Rodeway Inn":{"count":77},"Comfort Inn":{"count":128},"Best Western":{"count":57},"Quality Inn":{"count":91},"Holiday Inn Express":{"count":52},"Budget Inn":{"count":60}},"museum":{"Heimatmuseum":{"count":336},"Stadtmuseum":{"count":84},"Краеведческий музей":{"count":210},"Музей":{"count":83},"Tájház":{"count":89}},"attraction":{"Kursächsische Postmeilensäule":{"count":54},"Lavoir":{"count":78},"Sommerrodelbahn":{"count":60},"Часовня":{"count":66},"Колесо обозрения":{"count":54},"дольмен":{"count":112},"Усадьба":{"count":52},"Кладбище еврейское":{"count":91},"Приусадебный парк":{"count":69},"Хозяйственный двор":{"count":72},"OWŚ":{"count":106}},"camp_site":{"Camping":{"count":173},"Camping Municipal":{"count":184},"Camping municipal":{"count":77},"Campsite":{"count":59}},"chalet":{"Ferienwohnung":{"count":55}},"hostel":{"Общежитие":{"count":58}},"alpine_hut":{"КОШ":{"count":77}},"caravan_site":{"мк с Освещением ":{"count":97},"жб с Освещением ":{"count":65}}},"leisure":{"playground":{"Playground":{"count":569},"Abenteuerspielplatz":{"count":149},"Kinderspielplatz":{"count":268},"Waldspielplatz":{"count":170},"Spielplatz":{"count":264},"Bolzplatz":{"count":127},"Wasserspielplatz":{"count":148},"Játszótér":{"count":114},"Parque Infantil":{"count":385},"Parque":{"count":59},"Parque infantil":{"count":79},"Aire de Jeux":{"count":78},"Plac zabaw":{"count":255},"Dětské hřiště":{"count":77},"Детская площадка":{"count":200},"playground":{"count":118},"Tot Lot":{"count":121},"Jeux Enfants":{"count":51},"Parco giochi":{"count":58},"Zona Infantil":{"count":57}},"sports_centre":{"Kieser Training":{"count":95},"Turnhalle":{"count":612},"Virgin Active":{"count":69},"Planet Fitness":{"count":104},"Sporthalle":{"count":1056},"Schulsporthalle":{"count":85},"Palestra":{"count":74},"Sportplatz":{"count":100},"Schützenhaus":{"count":77},"Fitness First":{"count":67},"LA Fitness":{"count":106},"Reithalle":{"count":104},"McFit":{"count":59},"Спортзал":{"count":94},"Mrs. Sporty":{"count":75},"Tennishalle":{"count":164},"YMCA":{"count":166},"Hallenbad":{"count":79},"Palazzetto dello Sport":{"count":114},"24 Hour Fitness":{"count":52},"Mehrzweckhalle":{"count":152},"Gold's Gym":{"count":79},"Polideportivo":{"count":200},"Curves":{"count":88},"Tennis":{"count":109},"ДЮСШ":{"count":72},"Gymnase":{"count":360},"Salle Polyvalente":{"count":59},"ФОК":{"count":81},"Anytime Fitness":{"count":126},"Piscina Municipal":{"count":54},"Gym":{"count":80},"Hala sportowa":{"count":61},"Orlik":{"count":70},"Спорткомплекс":{"count":52},"Palestra Comunale":{"count":65},"Gymnasium":{"count":55},"Gimnasio":{"count":144},"Gimnasio Municipal":{"count":75},"Polideportivo Municipal":{"count":185},"Life Time Fitness":{"count":78},"Pabellón de Deportes":{"count":82},"Pabellón Municipal de Deportes":{"count":85}},"swimming_pool":{"Piscina municipal":{"count":77},"Piscine municipale":{"count":102},"Pool":{"count":170},"Piscine":{"count":97},"Piscina Comunale":{"count":59},"Swimming Pool":{"count":88},"Бассейн":{"count":62},"Piscina Municipal":{"count":178},"Piscina":{"count":145},"Nichtschwimmerbecken":{"count":57},"Sportbecken":{"count":54},"Kinderbecken":{"count":94},"piscina":{"count":62}}},"man_made":{"windmill":{"De Hoop":{"count":57}}}},"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"]]}],"phoneFormats":{"us":"+1-202-555-1234","ca":"+1-226-555-1234","bs":"+1-242-555-1234","bb":"+1-246-555-1234","ai":"+1-264-555-1234","ag":"+1-268-555-1234","vg":"+1-284-555-1234","vi":"+1-340-555-1234","ky":"+1-345-555-1234","bm":"+1-441-555-1234","gd":"+1-473-555-1234","tc":"+1-649-555-1234","ms":"+1-664-555-1234","mp":"+1-670-555-1234","gu":"+1-671-555-1234","as":"+1-684-555-1234","sx":"+1-721-555-1234","lc":"+1-758-555-1234","dm":"+1-767-555-1234","vc":"+1-784-555-1234","pr":"+1-787-555-1234","do":"+1-809-555-1234","tt":"+1-868-555-1234","kn":"+1-869-555-1234","jm":"+1-876-555-1234","za":"+27 11 907 1111","nl":"+31 42 123 4567","fr":"+33 1 23 45 67 89","es":"+34 989 12 34 56","pt":"+351 211 123456","fi":"+358 40 123 4567","hu":"+36 1 123 45 67","hr":"+385 01 123 4567","si":"+386 31 123 4567","it":"+39 01 123 456","va":"+39 01 123 456","gb":"+44 207 123456","gg":"+44 207 123456","im":"+44 207 123456","je":"+44 207 123456","se":"+46 31 123 4567","no":"+47 22 12 34 56","sj":"+47 22 12 34 56","pl":"+48 42 123 4567","de":"+49 89 1234567","br":"+55 11 0982 1098","ru":"+7 495 1234567","kz":"+7 495 1234567","vn":"+84 1 234 5678","hk":"+852 12345678"},"driveLeft":{"type":"FeatureCollection","features":[{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[113.573,22.186],[114,22.5],[114.05534,22.503],[114.0595,22.51422],[114.07345,22.51934],[114.0786,22.53012],[114.08512,22.53228],[114.09034,22.53717],[114.09611,22.53486],[114.10602,22.53472],[114.1115,22.52929],[114.11522,22.5308],[114.11649,22.53418],[114.11979,22.53511],[114.1244,22.5393],[114.12729,22.53947],[114.13018,22.54132],[114.13807,22.5432],[114.14429,22.54176],[114.14441,22.54114],[114.14846,22.54179],[114.14855,22.54397],[114.15042,22.54593],[114.14964,22.54954],[114.15166,22.55168],[114.15192,22.55438],[114.15642,22.55495],[114.15841,22.55909],[114.16032,22.56153],[114.16162,22.56187],[114.1634,22.55931],[114.16553,22.5593],[114.16733,22.56119],[114.16934,22.56093],[114.17061,22.5597],[114.17702,22.56],[114.17798,22.55546],[114.18401,22.5552],[114.18673,22.55468],[114.1878,22.55545],[114.18979,22.55446],[114.1955,22.55564],[114.19674,22.55691],[114.20005,22.55717],[114.20376,22.55623],[114.20884,22.55672],[114.22438,22.55055],[114.2264,22.5476],[114.22545,22.54528],[114.22661,22.54339],[114.32,22.576],[114.45,22.43],[114.45,22.14],[113.9,22.14],[113.75,22.22],[113.553,22.095],[113.54678,22.1207],[113.5456,22.1207],[113.54076,22.12373],[113.54016,22.13618],[113.54701,22.13651],[113.5475,22.14583],[113.52456,22.17978],[113.53623,22.20191],[113.53299,22.21232],[113.53497,22.21351],[113.53735,22.21377],[113.54156,22.21315],[113.54385,22.21709],[113.55849,22.21565],[113.573,22.186]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-75,18],[-80,20.5],[-83,19],[-77,16],[-75,18]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-64.33594,32.86113],[-79.39819,27.21067],[-80.63965,23.71998],[-73.39966,20.40642],[-65.1709,19.20743],[-65.09399,16.23577],[-59.13391,16.80454],[-62.64404,15.16228],[-59.43054,14.85985],[-62.83081,13.64599],[-61.80359,10.73752],[-62.08649,10.04729],[-61.06201,9.85522],[-59.81369,8.31274],[-59.8027,8.27469],[-59.83498,8.22712],[-59.94141,8.21149],[-59.99771,8.15576],[-59.97986,8.13265],[-59.99771,8.12041],[-60.00183,8.07147],[-60.05127,8.02524],[-60.09933,8.03747],[-60.12268,8.02388],[-60.14053,7.98988],[-60.36163,7.83345],[-60.53467,7.81713],[-60.5896,7.6375],[-60.72144,7.54493],[-60.5896,7.31888],[-60.63904,7.24532],[-60.54703,7.12542],[-60.46875,7.20309],[-60.37262,7.18401],[-60.29984,7.1445],[-60.2916,7.06819],[-60.39871,6.95097],[-60.66513,6.83235],[-60.71869,6.75053],[-60.91232,6.81735],[-60.94254,6.72053],[-61.14441,6.72326],[-61.23093,6.5773],[-61.1554,6.45314],[-61.14441,6.20199],[-61.39709,5.95619],[-60.71045,5.20036],[-60.21606,5.23319],[-59.99634,5.06906],[-60.13916,4.51071],[-59.69971,4.40118],[-59.5459,3.93002],[-59.87549,3.56825],[-59.7876,3.37086],[-60.01831,2.83332],[-59.90845,2.38335],[-59.69971,2.2626],[-59.77661,1.87833],[-59.65302,1.85087],[-59.69147,1.75754],[-59.61456,1.71361],[-59.55139,1.73283],[-59.36188,1.49123],[-59.26575,1.39238],[-58.92242,1.30726],[-58.83728,1.17271],[-58.71918,1.23037],[-58.71094,1.29902],[-58.49121,1.26058],[-58.461,1.37591],[-58.50494,1.38689],[-58.51044,1.46102],[-58.38135,1.4775],[-58.32642,1.57359],[-58.00507,1.49946],[-57.99133,1.65321],[-57.79907,1.69165],[-57.70844,1.71087],[-57.54364,1.68341],[-57.41455,1.94421],[-57.10693,1.97715],[-56.8103,1.85636],[-56.48071,1.92225],[-55.90942,1.81244],[-55.90942,2.04302],[-56.14014,2.26534],[-55.94788,2.53701],[-55.70892,2.39981],[-55.37933,2.43274],[-55.19257,2.53976],[-54.98108,2.57268],[-54.88495,2.43548],[-54.71191,2.46293],[-54.69543,2.34767],[-54.58832,2.32846],[-54.43451,2.43548],[-54.20654,2.76748],[-54.17358,3.12955],[-53.96484,3.57921],[-54.33838,4.00674],[-54.44412,4.52577],[-54.46884,4.91036],[-54.36653,5.13061],[-54.27727,5.26191],[-54.19968,5.3084],[-54.01222,5.54457],[-54.0239,5.64605],[-53.86322,5.94936],[-64.33594,32.86113]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-14.5,-6],[11.79657,-17.27197],[12.03415,-17.14866],[12.38159,-17.22213],[12.58484,-17.22476],[13.01193,-16.97405],[13.24951,-17.00098],[13.38135,-16.98522],[13.93341,-17.38734],[18.42476,-17.38996],[18.47763,-17.46857],[18.62663,-17.64599],[18.79211,-17.76177],[18.92944,-17.82061],[19.33044,-17.84806],[19.66278,-17.8644],[19.74792,-17.90557],[19.85161,-17.87486],[20.10361,-17.90296],[20.18394,-17.88401],[20.34737,-17.88466],[20.44693,-17.91733],[20.51697,-17.96698],[20.83008,-18.03032],[20.95711,-17.97285],[21.16997,-17.93497],[21.42677,-18.0264],[23.45032,-17.63879],[22.00012,-16.38866],[21.99944,-13.00523],[24.03809,-12.99118],[24.03809,-10.91962],[24.43359,-11.09217],[24.45557,-11.48002],[25.37842,-11.19996],[25.42236,-11.60919],[26.96045,-11.97484],[27.18018,-11.60919],[28.125,-12.42048],[29.11377,-13.36824],[29.1687,-13.43771],[29.55872,-13.19716],[29.68506,-13.2239],[29.62463,-13.41099],[29.80591,-13.44305],[29.81415,-12.14809],[29.31152,-12.55456],[28.41064,-11.78133],[28.63037,-10.70379],[28.65234,-9.73071],[28.37219,-9.24309],[28.89748,-8.47916],[30.78644,-8.26857],[29.39941,-6.05316],[29.4873,-4.45595],[29.75922,-4.46759],[29.81415,-4.36421],[29.88007,-4.36832],[30.04074,-4.26699],[30.07919,-4.1629],[30.18356,-4.08311],[30.1918,-4.05126],[30.21566,-4.04595],[30.22923,-4.01136],[30.21326,-3.99612],[30.25978,-3.88755],[30.29274,-3.86288],[30.34424,-3.77245],[30.39848,-3.79095],[30.40878,-3.76765],[30.39548,-3.7304],[30.39054,-3.72821],[30.3896,-3.71918],[30.39093,-3.7101],[30.39514,-3.70444],[30.42028,-3.64963],[30.46886,-3.53501],[30.67108,-3.41335],[30.63297,-3.34892],[30.84206,-3.25535],[30.84549,-3.16108],[30.83485,-3.09698],[30.7933,-3.06235],[30.82111,-3.02258],[30.84515,-2.9739],[30.74764,-2.99618],[30.7037,-2.97013],[30.66422,-2.98967],[30.57632,-2.90738],[30.49393,-2.94441],[30.41016,-2.87172],[30.52002,-2.39432],[30.77545,-2.38883],[30.8606,-2.31199],[30.84961,-2.19398],[30.89081,-2.07322],[30.81116,-1.96068],[30.83862,-1.6587],[30.73425,-1.4418],[30.56259,-1.33884],[30.4541,-1.05737],[30.35797,-1.06287],[30.34149,-1.13152],[30.16571,-1.34296],[29.91852,-1.48024],[29.83887,-1.31824],[29.58344,-1.39238],[29.729,0.05493],[29.96796,0.5136],[29.9707,0.8569],[30.22339,0.92281],[30.24536,1.15349],[30.47745,1.20772],[31.30966,2.15693],[31.20255,2.22211],[31.20255,2.29278],[31.16409,2.27906],[31.13937,2.28318],[31.13113,2.26534],[31.07826,2.30033],[31.0714,2.34767],[31.00479,2.4005],[30.97183,2.40461],[30.94711,2.38746],[30.94849,2.36276],[30.9375,2.33532],[30.88531,2.34012],[30.83038,2.42176],[30.74112,2.43274],[30.76035,2.5864],[30.90179,2.88132],[30.76447,3.04178],[30.93613,3.40239],[30.94059,3.50588],[30.85236,3.48601],[30.90866,3.5936],[30.95055,3.63918],[30.94677,3.65391],[30.9866,3.70187],[31.00582,3.70701],[31.02058,3.69708],[31.16547,3.7954],[31.28838,3.79643],[31.52699,3.66282],[31.7038,3.72449],[31.82671,3.82794],[31.96198,3.65596],[31.95854,3.57099],[32.04987,3.59155],[32.07733,3.57099],[32.0842,3.53672],[32.20093,3.50657],[32.21672,3.56448],[32.19578,3.59977],[32.41516,3.74504],[32.72055,3.76782],[32.89307,3.81219],[33.02782,3.89371],[33.18146,3.7793],[33.51173,3.75258],[33.98758,4.23309],[34.05762,4.28342],[34.38721,4.61065],[35.94452,4.62023],[35.95688,4.53467],[36.04134,4.44568],[36.89621,4.4491],[38.14728,3.62992],[38.55927,3.62033],[38.92181,3.51068],[39.56039,3.43392],[39.87076,3.87522],[40.76752,4.28753],[41.16371,3.94372],[41.89774,3.97797],[41.31271,3.14463],[40.98896,2.82869],[40.99548,-0.84042],[41.7,-1.8],[41.7,-49],[-27,-60],[-65.7,-52.5],[-14.5,-6]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[31.33301,35.47856],[33.0249,33.75175],[35.44189,36.02245],[31.33301,35.47856]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[14,36.5],[15,36],[14,35],[14,36.5]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[0,62],[2.5,51.3],[-2,50],[-1.9,49],[-20,53],[0,62]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[180,-35],[161,-19],[167,-12],[180,-22],[180,4],[170,3.7],[127,5.7],[118,2.7],[119.5,5.4],[117.2,7.5],[102.6,8],[102.9158,11.74099],[102.76268,12.07357],[102.70226,12.17158],[102.74139,12.46474],[102.53128,12.68857],[102.49557,12.9256],[102.49763,13.0064],[102.4597,13.08199],[102.43412,13.09026],[102.39155,13.16407],[102.35481,13.29341],[102.35893,13.30945],[102.34503,13.34837],[102.35928,13.39797],[102.3567,13.48095],[102.36168,13.50582],[102.33559,13.53787],[102.33971,13.56023],[102.35498,13.5649],[102.36511,13.5785],[102.40047,13.5679],[102.42537,13.56891],[102.44614,13.56123],[102.48047,13.57091],[102.53849,13.56757],[102.5699,13.58526],[102.57806,13.60486],[102.62501,13.60845],[102.62132,13.61295],[102.60767,13.61562],[102.57231,13.63331],[102.56922,13.64082],[102.54879,13.658],[102.56252,13.68552],[102.5972,13.70803],[102.67084,13.74472],[102.68818,13.75172],[102.7014,13.7684],[102.73161,13.77082],[102.76543,13.85541],[102.78397,13.93207],[102.80388,13.94406],[102.81607,13.96639],[102.90705,14.02119],[102.89726,14.0535],[102.90095,14.0838],[102.92421,14.10744],[102.92378,14.12838],[102.94147,14.15035],[102.92953,14.17952],[103.17535,14.33774],[103.19939,14.32992],[103.68553,14.44],[103.94508,14.34157],[104.05756,14.34589],[104.06636,14.3419],[104.26025,14.37749],[104.50058,14.36984],[104.57817,14.36019],[104.6422,14.42387],[104.66632,14.40234],[104.68357,14.39877],[104.71138,14.43169],[104.72305,14.42188],[104.71687,14.40043],[104.75344,14.40459],[104.80408,14.43867],[104.83429,14.41573],[104.99239,14.3838],[105.05402,14.19783],[105.47905,14.49186],[105.60883,15.0005],[105.46703,15.13005],[105.48866,15.20237],[105.59269,15.2716],[105.58617,15.32823],[105.50308,15.31912],[105.46703,15.33948],[105.49175,15.37921],[105.59372,15.42869],[105.59372,15.50927],[105.60986,15.54871],[105.62616,15.56492],[105.62702,15.59129],[105.63518,15.62742],[105.63612,15.66056],[105.5975,15.72088],[105.49965,15.76681],[105.46291,15.74517],[105.43819,15.75459],[105.40489,15.79424],[105.34241,15.92039],[105.37811,15.98344],[105.39167,15.99136],[105.41931,15.98608],[105.42652,15.99764],[105.41468,16.01661],[105.21263,16.05076],[105.04955,16.10552],[105.01316,16.24401],[104.88235,16.37812],[104.8391,16.45782],[104.77936,16.49041],[104.73919,16.53287],[104.74228,16.62205],[104.76391,16.70953],[104.73953,16.80323],[104.76425,16.85088],[104.73782,16.90968],[104.744,17.0128],[104.81266,17.21853],[104.79841,17.39274],[104.70348,17.52833],[104.46384,17.65515],[104.34368,17.83564],[104.27776,17.8559],[104.22661,17.98069],[104.1116,18.10735],[104.06525,18.21174],[103.97392,18.33823],[103.9286,18.33237],[103.88809,18.29456],[103.85582,18.28673],[103.83659,18.32715],[103.79128,18.3467],[103.70201,18.34214],[103.60931,18.40405],[103.57292,18.40437],[103.51593,18.42978],[103.45963,18.42587],[103.41568,18.44802],[103.30479,18.43206],[103.24265,18.37082],[103.24333,18.34133],[103.29123,18.32357],[103.28899,18.29521],[103.23595,18.28299],[103.16608,18.25511],[103.02429,17.98135],[102.6535,17.83237],[102.40631,17.99963],[102.10968,18.22413],[101.548,17.81538],[101.30493,17.64991],[101.14563,17.46595],[100.95886,17.61654],[101.01757,17.88858],[101.18752,18.05121],[101.16863,18.10409],[101.18134,18.33595],[101.08727,18.38287],[101.05499,18.43988],[101.23215,18.73015],[101.35265,19.04524],[101.25927,19.12733],[101.2373,19.32637],[101.25824,19.58438],[101.11954,19.56836],[101.08898,19.58777],[101.08624,19.59715],[101.03165,19.6185],[100.89844,19.62125],[100.77827,19.49249],[100.63751,19.56432],[100.58258,19.49313],[100.47478,19.5944],[100.42929,19.67152],[100.43341,19.7024],[100.4147,19.7255],[100.40525,19.7646],[100.43907,19.80345],[100.45555,19.84843],[100.50636,19.87264],[100.51709,19.93027],[100.58653,20.1599],[100.56576,20.1757],[100.54945,20.17473],[100.52731,20.14379],[100.51065,20.14895],[100.48697,20.17956],[100.46774,20.196],[100.45246,20.20147],[100.45521,20.22129],[100.44783,20.23546],[100.41607,20.25286],[100.40594,20.28184],[100.38397,20.31082],[100.37556,20.35187],[100.36165,20.35638],[100.35736,20.37408],[100.33195,20.39902],[100.27805,20.40224],[100.25917,20.39677],[100.2475,20.37263],[100.22535,20.35509],[100.22346,20.31839],[100.16579,20.29988],[100.17162,20.24545],[100.10845,20.25221],[100.09266,20.2696],[100.09798,20.31485],[100.07961,20.3678],[99.9567,20.46417],[99.91636,20.44925],[99.90765,20.44977],[99.89121,20.44511],[99.87276,20.44406],[99.86212,20.44326],[99.80186,20.33948],[99.46472,20.3884],[99.56085,20.20035],[99.43691,20.08882],[99.27727,20.11623],[99.06921,20.1101],[98.97789,19.74538],[98.24387,19.68656],[97.85934,19.57014],[97.76733,18.57336],[97.39655,18.47179],[97.62451,18.30238],[97.73849,17.97743],[97.66502,17.87943],[97.90947,17.56745],[98.52951,16.82557],[98.51303,16.69276],[98.69293,16.26873],[98.87421,16.43609],[98.93394,16.3353],[98.84743,16.13356],[98.74512,16.12037],[98.58307,16.07287],[98.5762,15.79754],[98.54736,15.37557],[98.17383,15.15167],[98.3606,14.63674],[99.08295,13.89208],[99.16534,13.72204],[99.18182,13.00723],[99.39331,12.56797],[99.64153,11.78973],[99.32156,11.30266],[98.77859,10.67849],[98.80597,10.47642],[98.76657,10.40459],[98.74924,10.34194],[96.85547,6.40265],[92.42523,20.54794],[92.2728,20.96272],[92.187,21.16],[92.26,21.36],[92.27,21.4328],[92.62,21.43],[92.6,22],[93.22,22.25],[93.4,23.7],[93.34,23.95],[94.155,23.847],[94.17,23.92],[94.25171,24.07405],[94.28,24.23],[94.30175,24.2371],[94.3256,24.2731],[94.6,24.7],[94.78,25.47],[95.2,26],[95.1,26.6],[97.3,27.9],[96.14,29.38],[95.4,29.1],[94.8,29.2],[92.5,27.8],[91.64,27.76],[91.4,28],[89.58,28.18],[88.9,27.32],[88.74,27.47],[88.9,27.86],[88.7,28.1],[88.1,27.87],[85.93,27.942],[81.6,30.5],[81.2,30],[78.73,31.5],[78.77,31.99],[78.4,32.5],[79.3,32.5],[79,34.3],[78.3,34.6],[78,35.5],[76.1,35.8],[76,36.55],[75.15,37],[72.5,36.9],[71.1,36.1],[71.65,35.44],[71.45,35],[70.985,34.54],[71.18,34.36],[71.092,34.118],[70.88,33.97],[70.5,33.94],[69.908,34.04],[69.869,33.96],[70,33.75],[70.13,33.73],[70.34,33.34],[70.013,33.14],[69.57,33.09],[69.24,32.45],[69.3,31.9],[68.1,31.6],[66.393,30.934],[66.2,29.8],[62.5,29.4],[60.87,29.86],[61.53,29.0165],[61.66,28.77],[61.96,28.54],[62.43,28.42],[62.6,28.25],[62.795,28.28],[62.86,27.25],[63.24,27.25],[63.327,27.13],[63.25,27.1],[63.25,26.84],[63.18,26.83],[63.18,26.65],[62.3,26.5],[62.2,26.28],[61.85,26.22],[61.84,25.75],[61.68,25.67],[56.5,-21],[180,-65],[180,-35]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[138.7,46.7],[145.5,44.5],[145.2,43.7],[146,43.3],[142,18],[122,24.3],[138.7,46.7]]]}},{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[-180,7],[-148,7],[-151,-12],[-171.5,-10.75],[-171,-16],[-152,-19],[-180,-55],[-180,7]]]}}]}};