]> git.openstreetmap.org Git - rails.git/blob - vendor/assets/iD/iD.js
Fix misspelling (lon -> lng)
[rails.git] / vendor / assets / iD / iD.js
1 (function () {
2 function actionAddEntity(way) {
3     return function(graph) {
4         return graph.replace(way);
5     };
6 }
7
8 var commonjsGlobal = typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
9
10 function commonjsRequire () {
11         throw new Error('Dynamic requires are not currently supported by rollup-plugin-commonjs');
12 }
13
14
15
16 function createCommonjsModule(fn, module) {
17         return module = { exports: {} }, fn(module, module.exports), module.exports;
18 }
19
20 var lodash = createCommonjsModule(function (module, exports) {
21 /**
22  * @license
23  * Lodash <https://lodash.com/>
24  * Copyright JS Foundation and other contributors <https://js.foundation/>
25  * Released under MIT license <https://lodash.com/license>
26  * Based on Underscore.js 1.8.3 <http://underscorejs.org/LICENSE>
27  * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors
28  */
29 (function() {
30
31   /** Used as a safe reference for `undefined` in pre-ES5 environments. */
32   var undefined;
33
34   /** Used as the semantic version number. */
35   var VERSION = '4.17.0';
36
37   /** Used as the size to enable large array optimizations. */
38   var LARGE_ARRAY_SIZE = 200;
39
40   /** Error message constants. */
41   var CORE_ERROR_TEXT = 'Unsupported core-js use. Try https://npms.io/search?q=ponyfill.',
42       FUNC_ERROR_TEXT = 'Expected a function';
43
44   /** Used to stand-in for `undefined` hash values. */
45   var HASH_UNDEFINED = '__lodash_hash_undefined__';
46
47   /** Used as the maximum memoize cache size. */
48   var MAX_MEMOIZE_SIZE = 500;
49
50   /** Used as the internal argument placeholder. */
51   var PLACEHOLDER = '__lodash_placeholder__';
52
53   /** Used to compose bitmasks for cloning. */
54   var CLONE_DEEP_FLAG = 1,
55       CLONE_FLAT_FLAG = 2,
56       CLONE_SYMBOLS_FLAG = 4;
57
58   /** Used to compose bitmasks for value comparisons. */
59   var COMPARE_PARTIAL_FLAG = 1,
60       COMPARE_UNORDERED_FLAG = 2;
61
62   /** Used to compose bitmasks for function metadata. */
63   var WRAP_BIND_FLAG = 1,
64       WRAP_BIND_KEY_FLAG = 2,
65       WRAP_CURRY_BOUND_FLAG = 4,
66       WRAP_CURRY_FLAG = 8,
67       WRAP_CURRY_RIGHT_FLAG = 16,
68       WRAP_PARTIAL_FLAG = 32,
69       WRAP_PARTIAL_RIGHT_FLAG = 64,
70       WRAP_ARY_FLAG = 128,
71       WRAP_REARG_FLAG = 256,
72       WRAP_FLIP_FLAG = 512;
73
74   /** Used as default options for `_.truncate`. */
75   var DEFAULT_TRUNC_LENGTH = 30,
76       DEFAULT_TRUNC_OMISSION = '...';
77
78   /** Used to detect hot functions by number of calls within a span of milliseconds. */
79   var HOT_COUNT = 800,
80       HOT_SPAN = 16;
81
82   /** Used to indicate the type of lazy iteratees. */
83   var LAZY_FILTER_FLAG = 1,
84       LAZY_MAP_FLAG = 2,
85       LAZY_WHILE_FLAG = 3;
86
87   /** Used as references for various `Number` constants. */
88   var INFINITY = 1 / 0,
89       MAX_SAFE_INTEGER = 9007199254740991,
90       MAX_INTEGER = 1.7976931348623157e+308,
91       NAN = 0 / 0;
92
93   /** Used as references for the maximum length and index of an array. */
94   var MAX_ARRAY_LENGTH = 4294967295,
95       MAX_ARRAY_INDEX = MAX_ARRAY_LENGTH - 1,
96       HALF_MAX_ARRAY_LENGTH = MAX_ARRAY_LENGTH >>> 1;
97
98   /** Used to associate wrap methods with their bit flags. */
99   var wrapFlags = [
100     ['ary', WRAP_ARY_FLAG],
101     ['bind', WRAP_BIND_FLAG],
102     ['bindKey', WRAP_BIND_KEY_FLAG],
103     ['curry', WRAP_CURRY_FLAG],
104     ['curryRight', WRAP_CURRY_RIGHT_FLAG],
105     ['flip', WRAP_FLIP_FLAG],
106     ['partial', WRAP_PARTIAL_FLAG],
107     ['partialRight', WRAP_PARTIAL_RIGHT_FLAG],
108     ['rearg', WRAP_REARG_FLAG]
109   ];
110
111   /** `Object#toString` result references. */
112   var argsTag = '[object Arguments]',
113       arrayTag = '[object Array]',
114       asyncTag = '[object AsyncFunction]',
115       boolTag = '[object Boolean]',
116       dateTag = '[object Date]',
117       domExcTag = '[object DOMException]',
118       errorTag = '[object Error]',
119       funcTag = '[object Function]',
120       genTag = '[object GeneratorFunction]',
121       mapTag = '[object Map]',
122       numberTag = '[object Number]',
123       nullTag = '[object Null]',
124       objectTag = '[object Object]',
125       promiseTag = '[object Promise]',
126       proxyTag = '[object Proxy]',
127       regexpTag = '[object RegExp]',
128       setTag = '[object Set]',
129       stringTag = '[object String]',
130       symbolTag = '[object Symbol]',
131       undefinedTag = '[object Undefined]',
132       weakMapTag = '[object WeakMap]',
133       weakSetTag = '[object WeakSet]';
134
135   var arrayBufferTag = '[object ArrayBuffer]',
136       dataViewTag = '[object DataView]',
137       float32Tag = '[object Float32Array]',
138       float64Tag = '[object Float64Array]',
139       int8Tag = '[object Int8Array]',
140       int16Tag = '[object Int16Array]',
141       int32Tag = '[object Int32Array]',
142       uint8Tag = '[object Uint8Array]',
143       uint8ClampedTag = '[object Uint8ClampedArray]',
144       uint16Tag = '[object Uint16Array]',
145       uint32Tag = '[object Uint32Array]';
146
147   /** Used to match empty string literals in compiled template source. */
148   var reEmptyStringLeading = /\b__p \+= '';/g,
149       reEmptyStringMiddle = /\b(__p \+=) '' \+/g,
150       reEmptyStringTrailing = /(__e\(.*?\)|\b__t\)) \+\n'';/g;
151
152   /** Used to match HTML entities and HTML characters. */
153   var reEscapedHtml = /&(?:amp|lt|gt|quot|#39);/g,
154       reUnescapedHtml = /[&<>"']/g,
155       reHasEscapedHtml = RegExp(reEscapedHtml.source),
156       reHasUnescapedHtml = RegExp(reUnescapedHtml.source);
157
158   /** Used to match template delimiters. */
159   var reEscape = /<%-([\s\S]+?)%>/g,
160       reEvaluate = /<%([\s\S]+?)%>/g,
161       reInterpolate = /<%=([\s\S]+?)%>/g;
162
163   /** Used to match property names within property paths. */
164   var reIsDeepProp = /\.|\[(?:[^[\]]*|(["'])(?:(?!\1)[^\\]|\\.)*?\1)\]/,
165       reIsPlainProp = /^\w*$/,
166       reLeadingDot = /^\./,
167       rePropName = /[^.[\]]+|\[(?:(-?\d+(?:\.\d+)?)|(["'])((?:(?!\2)[^\\]|\\.)*?)\2)\]|(?=(?:\.|\[\])(?:\.|\[\]|$))/g;
168
169   /**
170    * Used to match `RegExp`
171    * [syntax characters](http://ecma-international.org/ecma-262/7.0/#sec-patterns).
172    */
173   var reRegExpChar = /[\\^$.*+?()[\]{}|]/g,
174       reHasRegExpChar = RegExp(reRegExpChar.source);
175
176   /** Used to match leading and trailing whitespace. */
177   var reTrim = /^\s+|\s+$/g,
178       reTrimStart = /^\s+/,
179       reTrimEnd = /\s+$/;
180
181   /** Used to match wrap detail comments. */
182   var reWrapComment = /\{(?:\n\/\* \[wrapped with .+\] \*\/)?\n?/,
183       reWrapDetails = /\{\n\/\* \[wrapped with (.+)\] \*/,
184       reSplitDetails = /,? & /;
185
186   /** Used to match words composed of alphanumeric characters. */
187   var reAsciiWord = /[^\x00-\x2f\x3a-\x40\x5b-\x60\x7b-\x7f]+/g;
188
189   /** Used to match backslashes in property paths. */
190   var reEscapeChar = /\\(\\)?/g;
191
192   /**
193    * Used to match
194    * [ES template delimiters](http://ecma-international.org/ecma-262/7.0/#sec-template-literal-lexical-components).
195    */
196   var reEsTemplate = /\$\{([^\\}]*(?:\\.[^\\}]*)*)\}/g;
197
198   /** Used to match `RegExp` flags from their coerced string values. */
199   var reFlags = /\w*$/;
200
201   /** Used to detect bad signed hexadecimal string values. */
202   var reIsBadHex = /^[-+]0x[0-9a-f]+$/i;
203
204   /** Used to detect binary string values. */
205   var reIsBinary = /^0b[01]+$/i;
206
207   /** Used to detect host constructors (Safari). */
208   var reIsHostCtor = /^\[object .+?Constructor\]$/;
209
210   /** Used to detect octal string values. */
211   var reIsOctal = /^0o[0-7]+$/i;
212
213   /** Used to detect unsigned integer values. */
214   var reIsUint = /^(?:0|[1-9]\d*)$/;
215
216   /** Used to match Latin Unicode letters (excluding mathematical operators). */
217   var reLatin = /[\xc0-\xd6\xd8-\xf6\xf8-\xff\u0100-\u017f]/g;
218
219   /** Used to ensure capturing order of template delimiters. */
220   var reNoMatch = /($^)/;
221
222   /** Used to match unescaped characters in compiled string literals. */
223   var reUnescapedString = /['\n\r\u2028\u2029\\]/g;
224
225   /** Used to compose unicode character classes. */
226   var rsAstralRange = '\\ud800-\\udfff',
227       rsComboMarksRange = '\\u0300-\\u036f',
228       reComboHalfMarksRange = '\\ufe20-\\ufe2f',
229       rsComboSymbolsRange = '\\u20d0-\\u20ff',
230       rsComboRange = rsComboMarksRange + reComboHalfMarksRange + rsComboSymbolsRange,
231       rsDingbatRange = '\\u2700-\\u27bf',
232       rsLowerRange = 'a-z\\xdf-\\xf6\\xf8-\\xff',
233       rsMathOpRange = '\\xac\\xb1\\xd7\\xf7',
234       rsNonCharRange = '\\x00-\\x2f\\x3a-\\x40\\x5b-\\x60\\x7b-\\xbf',
235       rsPunctuationRange = '\\u2000-\\u206f',
236       rsSpaceRange = ' \\t\\x0b\\f\\xa0\\ufeff\\n\\r\\u2028\\u2029\\u1680\\u180e\\u2000\\u2001\\u2002\\u2003\\u2004\\u2005\\u2006\\u2007\\u2008\\u2009\\u200a\\u202f\\u205f\\u3000',
237       rsUpperRange = 'A-Z\\xc0-\\xd6\\xd8-\\xde',
238       rsVarRange = '\\ufe0e\\ufe0f',
239       rsBreakRange = rsMathOpRange + rsNonCharRange + rsPunctuationRange + rsSpaceRange;
240
241   /** Used to compose unicode capture groups. */
242   var rsApos = "['\u2019]",
243       rsAstral = '[' + rsAstralRange + ']',
244       rsBreak = '[' + rsBreakRange + ']',
245       rsCombo = '[' + rsComboRange + ']',
246       rsDigits = '\\d+',
247       rsDingbat = '[' + rsDingbatRange + ']',
248       rsLower = '[' + rsLowerRange + ']',
249       rsMisc = '[^' + rsAstralRange + rsBreakRange + rsDigits + rsDingbatRange + rsLowerRange + rsUpperRange + ']',
250       rsFitz = '\\ud83c[\\udffb-\\udfff]',
251       rsModifier = '(?:' + rsCombo + '|' + rsFitz + ')',
252       rsNonAstral = '[^' + rsAstralRange + ']',
253       rsRegional = '(?:\\ud83c[\\udde6-\\uddff]){2}',
254       rsSurrPair = '[\\ud800-\\udbff][\\udc00-\\udfff]',
255       rsUpper = '[' + rsUpperRange + ']',
256       rsZWJ = '\\u200d';
257
258   /** Used to compose unicode regexes. */
259   var rsMiscLower = '(?:' + rsLower + '|' + rsMisc + ')',
260       rsMiscUpper = '(?:' + rsUpper + '|' + rsMisc + ')',
261       rsOptContrLower = '(?:' + rsApos + '(?:d|ll|m|re|s|t|ve))?',
262       rsOptContrUpper = '(?:' + rsApos + '(?:D|LL|M|RE|S|T|VE))?',
263       reOptMod = rsModifier + '?',
264       rsOptVar = '[' + rsVarRange + ']?',
265       rsOptJoin = '(?:' + rsZWJ + '(?:' + [rsNonAstral, rsRegional, rsSurrPair].join('|') + ')' + rsOptVar + reOptMod + ')*',
266       rsOrdLower = '\\d*(?:(?:1st|2nd|3rd|(?![123])\\dth)\\b)',
267       rsOrdUpper = '\\d*(?:(?:1ST|2ND|3RD|(?![123])\\dTH)\\b)',
268       rsSeq = rsOptVar + reOptMod + rsOptJoin,
269       rsEmoji = '(?:' + [rsDingbat, rsRegional, rsSurrPair].join('|') + ')' + rsSeq,
270       rsSymbol = '(?:' + [rsNonAstral + rsCombo + '?', rsCombo, rsRegional, rsSurrPair, rsAstral].join('|') + ')';
271
272   /** Used to match apostrophes. */
273   var reApos = RegExp(rsApos, 'g');
274
275   /**
276    * Used to match [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks) and
277    * [combining diacritical marks for symbols](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks_for_Symbols).
278    */
279   var reComboMark = RegExp(rsCombo, 'g');
280
281   /** Used to match [string symbols](https://mathiasbynens.be/notes/javascript-unicode). */
282   var reUnicode = RegExp(rsFitz + '(?=' + rsFitz + ')|' + rsSymbol + rsSeq, 'g');
283
284   /** Used to match complex or compound words. */
285   var reUnicodeWord = RegExp([
286     rsUpper + '?' + rsLower + '+' + rsOptContrLower + '(?=' + [rsBreak, rsUpper, '$'].join('|') + ')',
287     rsMiscUpper + '+' + rsOptContrUpper + '(?=' + [rsBreak, rsUpper + rsMiscLower, '$'].join('|') + ')',
288     rsUpper + '?' + rsMiscLower + '+' + rsOptContrLower,
289     rsUpper + '+' + rsOptContrUpper,
290     rsOrdUpper,
291     rsOrdLower,
292     rsDigits,
293     rsEmoji
294   ].join('|'), 'g');
295
296   /** Used to detect strings with [zero-width joiners or code points from the astral planes](http://eev.ee/blog/2015/09/12/dark-corners-of-unicode/). */
297   var reHasUnicode = RegExp('[' + rsZWJ + rsAstralRange  + rsComboRange + rsVarRange + ']');
298
299   /** Used to detect strings that need a more robust regexp to match words. */
300   var reHasUnicodeWord = /[a-z][A-Z]|[A-Z]{2,}[a-z]|[0-9][a-zA-Z]|[a-zA-Z][0-9]|[^a-zA-Z0-9 ]/;
301
302   /** Used to assign default `context` object properties. */
303   var contextProps = [
304     'Array', 'Buffer', 'DataView', 'Date', 'Error', 'Float32Array', 'Float64Array',
305     'Function', 'Int8Array', 'Int16Array', 'Int32Array', 'Map', 'Math', 'Object',
306     'Promise', 'RegExp', 'Set', 'String', 'Symbol', 'TypeError', 'Uint8Array',
307     'Uint8ClampedArray', 'Uint16Array', 'Uint32Array', 'WeakMap',
308     '_', 'clearTimeout', 'isFinite', 'parseInt', 'setTimeout'
309   ];
310
311   /** Used to make template sourceURLs easier to identify. */
312   var templateCounter = -1;
313
314   /** Used to identify `toStringTag` values of typed arrays. */
315   var typedArrayTags = {};
316   typedArrayTags[float32Tag] = typedArrayTags[float64Tag] =
317   typedArrayTags[int8Tag] = typedArrayTags[int16Tag] =
318   typedArrayTags[int32Tag] = typedArrayTags[uint8Tag] =
319   typedArrayTags[uint8ClampedTag] = typedArrayTags[uint16Tag] =
320   typedArrayTags[uint32Tag] = true;
321   typedArrayTags[argsTag] = typedArrayTags[arrayTag] =
322   typedArrayTags[arrayBufferTag] = typedArrayTags[boolTag] =
323   typedArrayTags[dataViewTag] = typedArrayTags[dateTag] =
324   typedArrayTags[errorTag] = typedArrayTags[funcTag] =
325   typedArrayTags[mapTag] = typedArrayTags[numberTag] =
326   typedArrayTags[objectTag] = typedArrayTags[regexpTag] =
327   typedArrayTags[setTag] = typedArrayTags[stringTag] =
328   typedArrayTags[weakMapTag] = false;
329
330   /** Used to identify `toStringTag` values supported by `_.clone`. */
331   var cloneableTags = {};
332   cloneableTags[argsTag] = cloneableTags[arrayTag] =
333   cloneableTags[arrayBufferTag] = cloneableTags[dataViewTag] =
334   cloneableTags[boolTag] = cloneableTags[dateTag] =
335   cloneableTags[float32Tag] = cloneableTags[float64Tag] =
336   cloneableTags[int8Tag] = cloneableTags[int16Tag] =
337   cloneableTags[int32Tag] = cloneableTags[mapTag] =
338   cloneableTags[numberTag] = cloneableTags[objectTag] =
339   cloneableTags[regexpTag] = cloneableTags[setTag] =
340   cloneableTags[stringTag] = cloneableTags[symbolTag] =
341   cloneableTags[uint8Tag] = cloneableTags[uint8ClampedTag] =
342   cloneableTags[uint16Tag] = cloneableTags[uint32Tag] = true;
343   cloneableTags[errorTag] = cloneableTags[funcTag] =
344   cloneableTags[weakMapTag] = false;
345
346   /** Used to map Latin Unicode letters to basic Latin letters. */
347   var deburredLetters = {
348     // Latin-1 Supplement block.
349     '\xc0': 'A',  '\xc1': 'A', '\xc2': 'A', '\xc3': 'A', '\xc4': 'A', '\xc5': 'A',
350     '\xe0': 'a',  '\xe1': 'a', '\xe2': 'a', '\xe3': 'a', '\xe4': 'a', '\xe5': 'a',
351     '\xc7': 'C',  '\xe7': 'c',
352     '\xd0': 'D',  '\xf0': 'd',
353     '\xc8': 'E',  '\xc9': 'E', '\xca': 'E', '\xcb': 'E',
354     '\xe8': 'e',  '\xe9': 'e', '\xea': 'e', '\xeb': 'e',
355     '\xcc': 'I',  '\xcd': 'I', '\xce': 'I', '\xcf': 'I',
356     '\xec': 'i',  '\xed': 'i', '\xee': 'i', '\xef': 'i',
357     '\xd1': 'N',  '\xf1': 'n',
358     '\xd2': 'O',  '\xd3': 'O', '\xd4': 'O', '\xd5': 'O', '\xd6': 'O', '\xd8': 'O',
359     '\xf2': 'o',  '\xf3': 'o', '\xf4': 'o', '\xf5': 'o', '\xf6': 'o', '\xf8': 'o',
360     '\xd9': 'U',  '\xda': 'U', '\xdb': 'U', '\xdc': 'U',
361     '\xf9': 'u',  '\xfa': 'u', '\xfb': 'u', '\xfc': 'u',
362     '\xdd': 'Y',  '\xfd': 'y', '\xff': 'y',
363     '\xc6': 'Ae', '\xe6': 'ae',
364     '\xde': 'Th', '\xfe': 'th',
365     '\xdf': 'ss',
366     // Latin Extended-A block.
367     '\u0100': 'A',  '\u0102': 'A', '\u0104': 'A',
368     '\u0101': 'a',  '\u0103': 'a', '\u0105': 'a',
369     '\u0106': 'C',  '\u0108': 'C', '\u010a': 'C', '\u010c': 'C',
370     '\u0107': 'c',  '\u0109': 'c', '\u010b': 'c', '\u010d': 'c',
371     '\u010e': 'D',  '\u0110': 'D', '\u010f': 'd', '\u0111': 'd',
372     '\u0112': 'E',  '\u0114': 'E', '\u0116': 'E', '\u0118': 'E', '\u011a': 'E',
373     '\u0113': 'e',  '\u0115': 'e', '\u0117': 'e', '\u0119': 'e', '\u011b': 'e',
374     '\u011c': 'G',  '\u011e': 'G', '\u0120': 'G', '\u0122': 'G',
375     '\u011d': 'g',  '\u011f': 'g', '\u0121': 'g', '\u0123': 'g',
376     '\u0124': 'H',  '\u0126': 'H', '\u0125': 'h', '\u0127': 'h',
377     '\u0128': 'I',  '\u012a': 'I', '\u012c': 'I', '\u012e': 'I', '\u0130': 'I',
378     '\u0129': 'i',  '\u012b': 'i', '\u012d': 'i', '\u012f': 'i', '\u0131': 'i',
379     '\u0134': 'J',  '\u0135': 'j',
380     '\u0136': 'K',  '\u0137': 'k', '\u0138': 'k',
381     '\u0139': 'L',  '\u013b': 'L', '\u013d': 'L', '\u013f': 'L', '\u0141': 'L',
382     '\u013a': 'l',  '\u013c': 'l', '\u013e': 'l', '\u0140': 'l', '\u0142': 'l',
383     '\u0143': 'N',  '\u0145': 'N', '\u0147': 'N', '\u014a': 'N',
384     '\u0144': 'n',  '\u0146': 'n', '\u0148': 'n', '\u014b': 'n',
385     '\u014c': 'O',  '\u014e': 'O', '\u0150': 'O',
386     '\u014d': 'o',  '\u014f': 'o', '\u0151': 'o',
387     '\u0154': 'R',  '\u0156': 'R', '\u0158': 'R',
388     '\u0155': 'r',  '\u0157': 'r', '\u0159': 'r',
389     '\u015a': 'S',  '\u015c': 'S', '\u015e': 'S', '\u0160': 'S',
390     '\u015b': 's',  '\u015d': 's', '\u015f': 's', '\u0161': 's',
391     '\u0162': 'T',  '\u0164': 'T', '\u0166': 'T',
392     '\u0163': 't',  '\u0165': 't', '\u0167': 't',
393     '\u0168': 'U',  '\u016a': 'U', '\u016c': 'U', '\u016e': 'U', '\u0170': 'U', '\u0172': 'U',
394     '\u0169': 'u',  '\u016b': 'u', '\u016d': 'u', '\u016f': 'u', '\u0171': 'u', '\u0173': 'u',
395     '\u0174': 'W',  '\u0175': 'w',
396     '\u0176': 'Y',  '\u0177': 'y', '\u0178': 'Y',
397     '\u0179': 'Z',  '\u017b': 'Z', '\u017d': 'Z',
398     '\u017a': 'z',  '\u017c': 'z', '\u017e': 'z',
399     '\u0132': 'IJ', '\u0133': 'ij',
400     '\u0152': 'Oe', '\u0153': 'oe',
401     '\u0149': "'n", '\u017f': 's'
402   };
403
404   /** Used to map characters to HTML entities. */
405   var htmlEscapes = {
406     '&': '&amp;',
407     '<': '&lt;',
408     '>': '&gt;',
409     '"': '&quot;',
410     "'": '&#39;'
411   };
412
413   /** Used to map HTML entities to characters. */
414   var htmlUnescapes = {
415     '&amp;': '&',
416     '&lt;': '<',
417     '&gt;': '>',
418     '&quot;': '"',
419     '&#39;': "'"
420   };
421
422   /** Used to escape characters for inclusion in compiled string literals. */
423   var stringEscapes = {
424     '\\': '\\',
425     "'": "'",
426     '\n': 'n',
427     '\r': 'r',
428     '\u2028': 'u2028',
429     '\u2029': 'u2029'
430   };
431
432   /** Built-in method references without a dependency on `root`. */
433   var freeParseFloat = parseFloat,
434       freeParseInt = parseInt;
435
436   /** Detect free variable `global` from Node.js. */
437   var freeGlobal = typeof commonjsGlobal == 'object' && commonjsGlobal && commonjsGlobal.Object === Object && commonjsGlobal;
438
439   /** Detect free variable `self`. */
440   var freeSelf = typeof self == 'object' && self && self.Object === Object && self;
441
442   /** Used as a reference to the global object. */
443   var root = freeGlobal || freeSelf || Function('return this')();
444
445   /** Detect free variable `exports`. */
446   var freeExports = typeof exports == 'object' && exports && !exports.nodeType && exports;
447
448   /** Detect free variable `module`. */
449   var freeModule = freeExports && typeof module == 'object' && module && !module.nodeType && module;
450
451   /** Detect the popular CommonJS extension `module.exports`. */
452   var moduleExports = freeModule && freeModule.exports === freeExports;
453
454   /** Detect free variable `process` from Node.js. */
455   var freeProcess = moduleExports && freeGlobal.process;
456
457   /** Used to access faster Node.js helpers. */
458   var nodeUtil = (function() {
459     try {
460       return freeProcess && freeProcess.binding && freeProcess.binding('util');
461     } catch (e) {}
462   }());
463
464   /* Node.js helper references. */
465   var nodeIsArrayBuffer = nodeUtil && nodeUtil.isArrayBuffer,
466       nodeIsDate = nodeUtil && nodeUtil.isDate,
467       nodeIsMap = nodeUtil && nodeUtil.isMap,
468       nodeIsRegExp = nodeUtil && nodeUtil.isRegExp,
469       nodeIsSet = nodeUtil && nodeUtil.isSet,
470       nodeIsTypedArray = nodeUtil && nodeUtil.isTypedArray;
471
472   /*--------------------------------------------------------------------------*/
473
474   /**
475    * Adds the key-value `pair` to `map`.
476    *
477    * @private
478    * @param {Object} map The map to modify.
479    * @param {Array} pair The key-value pair to add.
480    * @returns {Object} Returns `map`.
481    */
482   function addMapEntry(map, pair) {
483     // Don't return `map.set` because it's not chainable in IE 11.
484     map.set(pair[0], pair[1]);
485     return map;
486   }
487
488   /**
489    * Adds `value` to `set`.
490    *
491    * @private
492    * @param {Object} set The set to modify.
493    * @param {*} value The value to add.
494    * @returns {Object} Returns `set`.
495    */
496   function addSetEntry(set, value) {
497     // Don't return `set.add` because it's not chainable in IE 11.
498     set.add(value);
499     return set;
500   }
501
502   /**
503    * A faster alternative to `Function#apply`, this function invokes `func`
504    * with the `this` binding of `thisArg` and the arguments of `args`.
505    *
506    * @private
507    * @param {Function} func The function to invoke.
508    * @param {*} thisArg The `this` binding of `func`.
509    * @param {Array} args The arguments to invoke `func` with.
510    * @returns {*} Returns the result of `func`.
511    */
512   function apply(func, thisArg, args) {
513     switch (args.length) {
514       case 0: return func.call(thisArg);
515       case 1: return func.call(thisArg, args[0]);
516       case 2: return func.call(thisArg, args[0], args[1]);
517       case 3: return func.call(thisArg, args[0], args[1], args[2]);
518     }
519     return func.apply(thisArg, args);
520   }
521
522   /**
523    * A specialized version of `baseAggregator` for arrays.
524    *
525    * @private
526    * @param {Array} [array] The array to iterate over.
527    * @param {Function} setter The function to set `accumulator` values.
528    * @param {Function} iteratee The iteratee to transform keys.
529    * @param {Object} accumulator The initial aggregated object.
530    * @returns {Function} Returns `accumulator`.
531    */
532   function arrayAggregator(array, setter, iteratee, accumulator) {
533     var index = -1,
534         length = array == null ? 0 : array.length;
535
536     while (++index < length) {
537       var value = array[index];
538       setter(accumulator, value, iteratee(value), array);
539     }
540     return accumulator;
541   }
542
543   /**
544    * A specialized version of `_.forEach` for arrays without support for
545    * iteratee shorthands.
546    *
547    * @private
548    * @param {Array} [array] The array to iterate over.
549    * @param {Function} iteratee The function invoked per iteration.
550    * @returns {Array} Returns `array`.
551    */
552   function arrayEach(array, iteratee) {
553     var index = -1,
554         length = array == null ? 0 : array.length;
555
556     while (++index < length) {
557       if (iteratee(array[index], index, array) === false) {
558         break;
559       }
560     }
561     return array;
562   }
563
564   /**
565    * A specialized version of `_.forEachRight` for arrays without support for
566    * iteratee shorthands.
567    *
568    * @private
569    * @param {Array} [array] The array to iterate over.
570    * @param {Function} iteratee The function invoked per iteration.
571    * @returns {Array} Returns `array`.
572    */
573   function arrayEachRight(array, iteratee) {
574     var length = array == null ? 0 : array.length;
575
576     while (length--) {
577       if (iteratee(array[length], length, array) === false) {
578         break;
579       }
580     }
581     return array;
582   }
583
584   /**
585    * A specialized version of `_.every` for arrays without support for
586    * iteratee shorthands.
587    *
588    * @private
589    * @param {Array} [array] The array to iterate over.
590    * @param {Function} predicate The function invoked per iteration.
591    * @returns {boolean} Returns `true` if all elements pass the predicate check,
592    *  else `false`.
593    */
594   function arrayEvery(array, predicate) {
595     var index = -1,
596         length = array == null ? 0 : array.length;
597
598     while (++index < length) {
599       if (!predicate(array[index], index, array)) {
600         return false;
601       }
602     }
603     return true;
604   }
605
606   /**
607    * A specialized version of `_.filter` for arrays without support for
608    * iteratee shorthands.
609    *
610    * @private
611    * @param {Array} [array] The array to iterate over.
612    * @param {Function} predicate The function invoked per iteration.
613    * @returns {Array} Returns the new filtered array.
614    */
615   function arrayFilter(array, predicate) {
616     var index = -1,
617         length = array == null ? 0 : array.length,
618         resIndex = 0,
619         result = [];
620
621     while (++index < length) {
622       var value = array[index];
623       if (predicate(value, index, array)) {
624         result[resIndex++] = value;
625       }
626     }
627     return result;
628   }
629
630   /**
631    * A specialized version of `_.includes` for arrays without support for
632    * specifying an index to search from.
633    *
634    * @private
635    * @param {Array} [array] The array to inspect.
636    * @param {*} target The value to search for.
637    * @returns {boolean} Returns `true` if `target` is found, else `false`.
638    */
639   function arrayIncludes(array, value) {
640     var length = array == null ? 0 : array.length;
641     return !!length && baseIndexOf(array, value, 0) > -1;
642   }
643
644   /**
645    * This function is like `arrayIncludes` except that it accepts a comparator.
646    *
647    * @private
648    * @param {Array} [array] The array to inspect.
649    * @param {*} target The value to search for.
650    * @param {Function} comparator The comparator invoked per element.
651    * @returns {boolean} Returns `true` if `target` is found, else `false`.
652    */
653   function arrayIncludesWith(array, value, comparator) {
654     var index = -1,
655         length = array == null ? 0 : array.length;
656
657     while (++index < length) {
658       if (comparator(value, array[index])) {
659         return true;
660       }
661     }
662     return false;
663   }
664
665   /**
666    * A specialized version of `_.map` for arrays without support for iteratee
667    * shorthands.
668    *
669    * @private
670    * @param {Array} [array] The array to iterate over.
671    * @param {Function} iteratee The function invoked per iteration.
672    * @returns {Array} Returns the new mapped array.
673    */
674   function arrayMap(array, iteratee) {
675     var index = -1,
676         length = array == null ? 0 : array.length,
677         result = Array(length);
678
679     while (++index < length) {
680       result[index] = iteratee(array[index], index, array);
681     }
682     return result;
683   }
684
685   /**
686    * Appends the elements of `values` to `array`.
687    *
688    * @private
689    * @param {Array} array The array to modify.
690    * @param {Array} values The values to append.
691    * @returns {Array} Returns `array`.
692    */
693   function arrayPush(array, values) {
694     var index = -1,
695         length = values.length,
696         offset = array.length;
697
698     while (++index < length) {
699       array[offset + index] = values[index];
700     }
701     return array;
702   }
703
704   /**
705    * A specialized version of `_.reduce` for arrays without support for
706    * iteratee shorthands.
707    *
708    * @private
709    * @param {Array} [array] The array to iterate over.
710    * @param {Function} iteratee The function invoked per iteration.
711    * @param {*} [accumulator] The initial value.
712    * @param {boolean} [initAccum] Specify using the first element of `array` as
713    *  the initial value.
714    * @returns {*} Returns the accumulated value.
715    */
716   function arrayReduce(array, iteratee, accumulator, initAccum) {
717     var index = -1,
718         length = array == null ? 0 : array.length;
719
720     if (initAccum && length) {
721       accumulator = array[++index];
722     }
723     while (++index < length) {
724       accumulator = iteratee(accumulator, array[index], index, array);
725     }
726     return accumulator;
727   }
728
729   /**
730    * A specialized version of `_.reduceRight` for arrays without support for
731    * iteratee shorthands.
732    *
733    * @private
734    * @param {Array} [array] The array to iterate over.
735    * @param {Function} iteratee The function invoked per iteration.
736    * @param {*} [accumulator] The initial value.
737    * @param {boolean} [initAccum] Specify using the last element of `array` as
738    *  the initial value.
739    * @returns {*} Returns the accumulated value.
740    */
741   function arrayReduceRight(array, iteratee, accumulator, initAccum) {
742     var length = array == null ? 0 : array.length;
743     if (initAccum && length) {
744       accumulator = array[--length];
745     }
746     while (length--) {
747       accumulator = iteratee(accumulator, array[length], length, array);
748     }
749     return accumulator;
750   }
751
752   /**
753    * A specialized version of `_.some` for arrays without support for iteratee
754    * shorthands.
755    *
756    * @private
757    * @param {Array} [array] The array to iterate over.
758    * @param {Function} predicate The function invoked per iteration.
759    * @returns {boolean} Returns `true` if any element passes the predicate check,
760    *  else `false`.
761    */
762   function arraySome(array, predicate) {
763     var index = -1,
764         length = array == null ? 0 : array.length;
765
766     while (++index < length) {
767       if (predicate(array[index], index, array)) {
768         return true;
769       }
770     }
771     return false;
772   }
773
774   /**
775    * Gets the size of an ASCII `string`.
776    *
777    * @private
778    * @param {string} string The string inspect.
779    * @returns {number} Returns the string size.
780    */
781   var asciiSize = baseProperty('length');
782
783   /**
784    * Converts an ASCII `string` to an array.
785    *
786    * @private
787    * @param {string} string The string to convert.
788    * @returns {Array} Returns the converted array.
789    */
790   function asciiToArray(string) {
791     return string.split('');
792   }
793
794   /**
795    * Splits an ASCII `string` into an array of its words.
796    *
797    * @private
798    * @param {string} The string to inspect.
799    * @returns {Array} Returns the words of `string`.
800    */
801   function asciiWords(string) {
802     return string.match(reAsciiWord) || [];
803   }
804
805   /**
806    * The base implementation of methods like `_.findKey` and `_.findLastKey`,
807    * without support for iteratee shorthands, which iterates over `collection`
808    * using `eachFunc`.
809    *
810    * @private
811    * @param {Array|Object} collection The collection to inspect.
812    * @param {Function} predicate The function invoked per iteration.
813    * @param {Function} eachFunc The function to iterate over `collection`.
814    * @returns {*} Returns the found element or its key, else `undefined`.
815    */
816   function baseFindKey(collection, predicate, eachFunc) {
817     var result;
818     eachFunc(collection, function(value, key, collection) {
819       if (predicate(value, key, collection)) {
820         result = key;
821         return false;
822       }
823     });
824     return result;
825   }
826
827   /**
828    * The base implementation of `_.findIndex` and `_.findLastIndex` without
829    * support for iteratee shorthands.
830    *
831    * @private
832    * @param {Array} array The array to inspect.
833    * @param {Function} predicate The function invoked per iteration.
834    * @param {number} fromIndex The index to search from.
835    * @param {boolean} [fromRight] Specify iterating from right to left.
836    * @returns {number} Returns the index of the matched value, else `-1`.
837    */
838   function baseFindIndex(array, predicate, fromIndex, fromRight) {
839     var length = array.length,
840         index = fromIndex + (fromRight ? 1 : -1);
841
842     while ((fromRight ? index-- : ++index < length)) {
843       if (predicate(array[index], index, array)) {
844         return index;
845       }
846     }
847     return -1;
848   }
849
850   /**
851    * The base implementation of `_.indexOf` without `fromIndex` bounds checks.
852    *
853    * @private
854    * @param {Array} array The array to inspect.
855    * @param {*} value The value to search for.
856    * @param {number} fromIndex The index to search from.
857    * @returns {number} Returns the index of the matched value, else `-1`.
858    */
859   function baseIndexOf(array, value, fromIndex) {
860     return value === value
861       ? strictIndexOf(array, value, fromIndex)
862       : baseFindIndex(array, baseIsNaN, fromIndex);
863   }
864
865   /**
866    * This function is like `baseIndexOf` except that it accepts a comparator.
867    *
868    * @private
869    * @param {Array} array The array to inspect.
870    * @param {*} value The value to search for.
871    * @param {number} fromIndex The index to search from.
872    * @param {Function} comparator The comparator invoked per element.
873    * @returns {number} Returns the index of the matched value, else `-1`.
874    */
875   function baseIndexOfWith(array, value, fromIndex, comparator) {
876     var index = fromIndex - 1,
877         length = array.length;
878
879     while (++index < length) {
880       if (comparator(array[index], value)) {
881         return index;
882       }
883     }
884     return -1;
885   }
886
887   /**
888    * The base implementation of `_.isNaN` without support for number objects.
889    *
890    * @private
891    * @param {*} value The value to check.
892    * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
893    */
894   function baseIsNaN(value) {
895     return value !== value;
896   }
897
898   /**
899    * The base implementation of `_.mean` and `_.meanBy` without support for
900    * iteratee shorthands.
901    *
902    * @private
903    * @param {Array} array The array to iterate over.
904    * @param {Function} iteratee The function invoked per iteration.
905    * @returns {number} Returns the mean.
906    */
907   function baseMean(array, iteratee) {
908     var length = array == null ? 0 : array.length;
909     return length ? (baseSum(array, iteratee) / length) : NAN;
910   }
911
912   /**
913    * The base implementation of `_.property` without support for deep paths.
914    *
915    * @private
916    * @param {string} key The key of the property to get.
917    * @returns {Function} Returns the new accessor function.
918    */
919   function baseProperty(key) {
920     return function(object) {
921       return object == null ? undefined : object[key];
922     };
923   }
924
925   /**
926    * The base implementation of `_.propertyOf` without support for deep paths.
927    *
928    * @private
929    * @param {Object} object The object to query.
930    * @returns {Function} Returns the new accessor function.
931    */
932   function basePropertyOf(object) {
933     return function(key) {
934       return object == null ? undefined : object[key];
935     };
936   }
937
938   /**
939    * The base implementation of `_.reduce` and `_.reduceRight`, without support
940    * for iteratee shorthands, which iterates over `collection` using `eachFunc`.
941    *
942    * @private
943    * @param {Array|Object} collection The collection to iterate over.
944    * @param {Function} iteratee The function invoked per iteration.
945    * @param {*} accumulator The initial value.
946    * @param {boolean} initAccum Specify using the first or last element of
947    *  `collection` as the initial value.
948    * @param {Function} eachFunc The function to iterate over `collection`.
949    * @returns {*} Returns the accumulated value.
950    */
951   function baseReduce(collection, iteratee, accumulator, initAccum, eachFunc) {
952     eachFunc(collection, function(value, index, collection) {
953       accumulator = initAccum
954         ? (initAccum = false, value)
955         : iteratee(accumulator, value, index, collection);
956     });
957     return accumulator;
958   }
959
960   /**
961    * The base implementation of `_.sortBy` which uses `comparer` to define the
962    * sort order of `array` and replaces criteria objects with their corresponding
963    * values.
964    *
965    * @private
966    * @param {Array} array The array to sort.
967    * @param {Function} comparer The function to define sort order.
968    * @returns {Array} Returns `array`.
969    */
970   function baseSortBy(array, comparer) {
971     var length = array.length;
972
973     array.sort(comparer);
974     while (length--) {
975       array[length] = array[length].value;
976     }
977     return array;
978   }
979
980   /**
981    * The base implementation of `_.sum` and `_.sumBy` without support for
982    * iteratee shorthands.
983    *
984    * @private
985    * @param {Array} array The array to iterate over.
986    * @param {Function} iteratee The function invoked per iteration.
987    * @returns {number} Returns the sum.
988    */
989   function baseSum(array, iteratee) {
990     var result,
991         index = -1,
992         length = array.length;
993
994     while (++index < length) {
995       var current = iteratee(array[index]);
996       if (current !== undefined) {
997         result = result === undefined ? current : (result + current);
998       }
999     }
1000     return result;
1001   }
1002
1003   /**
1004    * The base implementation of `_.times` without support for iteratee shorthands
1005    * or max array length checks.
1006    *
1007    * @private
1008    * @param {number} n The number of times to invoke `iteratee`.
1009    * @param {Function} iteratee The function invoked per iteration.
1010    * @returns {Array} Returns the array of results.
1011    */
1012   function baseTimes(n, iteratee) {
1013     var index = -1,
1014         result = Array(n);
1015
1016     while (++index < n) {
1017       result[index] = iteratee(index);
1018     }
1019     return result;
1020   }
1021
1022   /**
1023    * The base implementation of `_.toPairs` and `_.toPairsIn` which creates an array
1024    * of key-value pairs for `object` corresponding to the property names of `props`.
1025    *
1026    * @private
1027    * @param {Object} object The object to query.
1028    * @param {Array} props The property names to get values for.
1029    * @returns {Object} Returns the key-value pairs.
1030    */
1031   function baseToPairs(object, props) {
1032     return arrayMap(props, function(key) {
1033       return [key, object[key]];
1034     });
1035   }
1036
1037   /**
1038    * The base implementation of `_.unary` without support for storing metadata.
1039    *
1040    * @private
1041    * @param {Function} func The function to cap arguments for.
1042    * @returns {Function} Returns the new capped function.
1043    */
1044   function baseUnary(func) {
1045     return function(value) {
1046       return func(value);
1047     };
1048   }
1049
1050   /**
1051    * The base implementation of `_.values` and `_.valuesIn` which creates an
1052    * array of `object` property values corresponding to the property names
1053    * of `props`.
1054    *
1055    * @private
1056    * @param {Object} object The object to query.
1057    * @param {Array} props The property names to get values for.
1058    * @returns {Object} Returns the array of property values.
1059    */
1060   function baseValues(object, props) {
1061     return arrayMap(props, function(key) {
1062       return object[key];
1063     });
1064   }
1065
1066   /**
1067    * Checks if a `cache` value for `key` exists.
1068    *
1069    * @private
1070    * @param {Object} cache The cache to query.
1071    * @param {string} key The key of the entry to check.
1072    * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
1073    */
1074   function cacheHas(cache, key) {
1075     return cache.has(key);
1076   }
1077
1078   /**
1079    * Used by `_.trim` and `_.trimStart` to get the index of the first string symbol
1080    * that is not found in the character symbols.
1081    *
1082    * @private
1083    * @param {Array} strSymbols The string symbols to inspect.
1084    * @param {Array} chrSymbols The character symbols to find.
1085    * @returns {number} Returns the index of the first unmatched string symbol.
1086    */
1087   function charsStartIndex(strSymbols, chrSymbols) {
1088     var index = -1,
1089         length = strSymbols.length;
1090
1091     while (++index < length && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
1092     return index;
1093   }
1094
1095   /**
1096    * Used by `_.trim` and `_.trimEnd` to get the index of the last string symbol
1097    * that is not found in the character symbols.
1098    *
1099    * @private
1100    * @param {Array} strSymbols The string symbols to inspect.
1101    * @param {Array} chrSymbols The character symbols to find.
1102    * @returns {number} Returns the index of the last unmatched string symbol.
1103    */
1104   function charsEndIndex(strSymbols, chrSymbols) {
1105     var index = strSymbols.length;
1106
1107     while (index-- && baseIndexOf(chrSymbols, strSymbols[index], 0) > -1) {}
1108     return index;
1109   }
1110
1111   /**
1112    * Gets the number of `placeholder` occurrences in `array`.
1113    *
1114    * @private
1115    * @param {Array} array The array to inspect.
1116    * @param {*} placeholder The placeholder to search for.
1117    * @returns {number} Returns the placeholder count.
1118    */
1119   function countHolders(array, placeholder) {
1120     var length = array.length,
1121         result = 0;
1122
1123     while (length--) {
1124       if (array[length] === placeholder) {
1125         ++result;
1126       }
1127     }
1128     return result;
1129   }
1130
1131   /**
1132    * Used by `_.deburr` to convert Latin-1 Supplement and Latin Extended-A
1133    * letters to basic Latin letters.
1134    *
1135    * @private
1136    * @param {string} letter The matched letter to deburr.
1137    * @returns {string} Returns the deburred letter.
1138    */
1139   var deburrLetter = basePropertyOf(deburredLetters);
1140
1141   /**
1142    * Used by `_.escape` to convert characters to HTML entities.
1143    *
1144    * @private
1145    * @param {string} chr The matched character to escape.
1146    * @returns {string} Returns the escaped character.
1147    */
1148   var escapeHtmlChar = basePropertyOf(htmlEscapes);
1149
1150   /**
1151    * Used by `_.template` to escape characters for inclusion in compiled string literals.
1152    *
1153    * @private
1154    * @param {string} chr The matched character to escape.
1155    * @returns {string} Returns the escaped character.
1156    */
1157   function escapeStringChar(chr) {
1158     return '\\' + stringEscapes[chr];
1159   }
1160
1161   /**
1162    * Gets the value at `key` of `object`.
1163    *
1164    * @private
1165    * @param {Object} [object] The object to query.
1166    * @param {string} key The key of the property to get.
1167    * @returns {*} Returns the property value.
1168    */
1169   function getValue(object, key) {
1170     return object == null ? undefined : object[key];
1171   }
1172
1173   /**
1174    * Checks if `string` contains Unicode symbols.
1175    *
1176    * @private
1177    * @param {string} string The string to inspect.
1178    * @returns {boolean} Returns `true` if a symbol is found, else `false`.
1179    */
1180   function hasUnicode(string) {
1181     return reHasUnicode.test(string);
1182   }
1183
1184   /**
1185    * Checks if `string` contains a word composed of Unicode symbols.
1186    *
1187    * @private
1188    * @param {string} string The string to inspect.
1189    * @returns {boolean} Returns `true` if a word is found, else `false`.
1190    */
1191   function hasUnicodeWord(string) {
1192     return reHasUnicodeWord.test(string);
1193   }
1194
1195   /**
1196    * Converts `iterator` to an array.
1197    *
1198    * @private
1199    * @param {Object} iterator The iterator to convert.
1200    * @returns {Array} Returns the converted array.
1201    */
1202   function iteratorToArray(iterator) {
1203     var data,
1204         result = [];
1205
1206     while (!(data = iterator.next()).done) {
1207       result.push(data.value);
1208     }
1209     return result;
1210   }
1211
1212   /**
1213    * Converts `map` to its key-value pairs.
1214    *
1215    * @private
1216    * @param {Object} map The map to convert.
1217    * @returns {Array} Returns the key-value pairs.
1218    */
1219   function mapToArray(map) {
1220     var index = -1,
1221         result = Array(map.size);
1222
1223     map.forEach(function(value, key) {
1224       result[++index] = [key, value];
1225     });
1226     return result;
1227   }
1228
1229   /**
1230    * Creates a unary function that invokes `func` with its argument transformed.
1231    *
1232    * @private
1233    * @param {Function} func The function to wrap.
1234    * @param {Function} transform The argument transform.
1235    * @returns {Function} Returns the new function.
1236    */
1237   function overArg(func, transform) {
1238     return function(arg) {
1239       return func(transform(arg));
1240     };
1241   }
1242
1243   /**
1244    * Replaces all `placeholder` elements in `array` with an internal placeholder
1245    * and returns an array of their indexes.
1246    *
1247    * @private
1248    * @param {Array} array The array to modify.
1249    * @param {*} placeholder The placeholder to replace.
1250    * @returns {Array} Returns the new array of placeholder indexes.
1251    */
1252   function replaceHolders(array, placeholder) {
1253     var index = -1,
1254         length = array.length,
1255         resIndex = 0,
1256         result = [];
1257
1258     while (++index < length) {
1259       var value = array[index];
1260       if (value === placeholder || value === PLACEHOLDER) {
1261         array[index] = PLACEHOLDER;
1262         result[resIndex++] = index;
1263       }
1264     }
1265     return result;
1266   }
1267
1268   /**
1269    * Converts `set` to an array of its values.
1270    *
1271    * @private
1272    * @param {Object} set The set to convert.
1273    * @returns {Array} Returns the values.
1274    */
1275   function setToArray(set) {
1276     var index = -1,
1277         result = Array(set.size);
1278
1279     set.forEach(function(value) {
1280       result[++index] = value;
1281     });
1282     return result;
1283   }
1284
1285   /**
1286    * Converts `set` to its value-value pairs.
1287    *
1288    * @private
1289    * @param {Object} set The set to convert.
1290    * @returns {Array} Returns the value-value pairs.
1291    */
1292   function setToPairs(set) {
1293     var index = -1,
1294         result = Array(set.size);
1295
1296     set.forEach(function(value) {
1297       result[++index] = [value, value];
1298     });
1299     return result;
1300   }
1301
1302   /**
1303    * A specialized version of `_.indexOf` which performs strict equality
1304    * comparisons of values, i.e. `===`.
1305    *
1306    * @private
1307    * @param {Array} array The array to inspect.
1308    * @param {*} value The value to search for.
1309    * @param {number} fromIndex The index to search from.
1310    * @returns {number} Returns the index of the matched value, else `-1`.
1311    */
1312   function strictIndexOf(array, value, fromIndex) {
1313     var index = fromIndex - 1,
1314         length = array.length;
1315
1316     while (++index < length) {
1317       if (array[index] === value) {
1318         return index;
1319       }
1320     }
1321     return -1;
1322   }
1323
1324   /**
1325    * A specialized version of `_.lastIndexOf` which performs strict equality
1326    * comparisons of values, i.e. `===`.
1327    *
1328    * @private
1329    * @param {Array} array The array to inspect.
1330    * @param {*} value The value to search for.
1331    * @param {number} fromIndex The index to search from.
1332    * @returns {number} Returns the index of the matched value, else `-1`.
1333    */
1334   function strictLastIndexOf(array, value, fromIndex) {
1335     var index = fromIndex + 1;
1336     while (index--) {
1337       if (array[index] === value) {
1338         return index;
1339       }
1340     }
1341     return index;
1342   }
1343
1344   /**
1345    * Gets the number of symbols in `string`.
1346    *
1347    * @private
1348    * @param {string} string The string to inspect.
1349    * @returns {number} Returns the string size.
1350    */
1351   function stringSize(string) {
1352     return hasUnicode(string)
1353       ? unicodeSize(string)
1354       : asciiSize(string);
1355   }
1356
1357   /**
1358    * Converts `string` to an array.
1359    *
1360    * @private
1361    * @param {string} string The string to convert.
1362    * @returns {Array} Returns the converted array.
1363    */
1364   function stringToArray(string) {
1365     return hasUnicode(string)
1366       ? unicodeToArray(string)
1367       : asciiToArray(string);
1368   }
1369
1370   /**
1371    * Used by `_.unescape` to convert HTML entities to characters.
1372    *
1373    * @private
1374    * @param {string} chr The matched character to unescape.
1375    * @returns {string} Returns the unescaped character.
1376    */
1377   var unescapeHtmlChar = basePropertyOf(htmlUnescapes);
1378
1379   /**
1380    * Gets the size of a Unicode `string`.
1381    *
1382    * @private
1383    * @param {string} string The string inspect.
1384    * @returns {number} Returns the string size.
1385    */
1386   function unicodeSize(string) {
1387     var result = reUnicode.lastIndex = 0;
1388     while (reUnicode.test(string)) {
1389       ++result;
1390     }
1391     return result;
1392   }
1393
1394   /**
1395    * Converts a Unicode `string` to an array.
1396    *
1397    * @private
1398    * @param {string} string The string to convert.
1399    * @returns {Array} Returns the converted array.
1400    */
1401   function unicodeToArray(string) {
1402     return string.match(reUnicode) || [];
1403   }
1404
1405   /**
1406    * Splits a Unicode `string` into an array of its words.
1407    *
1408    * @private
1409    * @param {string} The string to inspect.
1410    * @returns {Array} Returns the words of `string`.
1411    */
1412   function unicodeWords(string) {
1413     return string.match(reUnicodeWord) || [];
1414   }
1415
1416   /*--------------------------------------------------------------------------*/
1417
1418   /**
1419    * Create a new pristine `lodash` function using the `context` object.
1420    *
1421    * @static
1422    * @memberOf _
1423    * @since 1.1.0
1424    * @category Util
1425    * @param {Object} [context=root] The context object.
1426    * @returns {Function} Returns a new `lodash` function.
1427    * @example
1428    *
1429    * _.mixin({ 'foo': _.constant('foo') });
1430    *
1431    * var lodash = _.runInContext();
1432    * lodash.mixin({ 'bar': lodash.constant('bar') });
1433    *
1434    * _.isFunction(_.foo);
1435    * // => true
1436    * _.isFunction(_.bar);
1437    * // => false
1438    *
1439    * lodash.isFunction(lodash.foo);
1440    * // => false
1441    * lodash.isFunction(lodash.bar);
1442    * // => true
1443    *
1444    * // Create a suped-up `defer` in Node.js.
1445    * var defer = _.runInContext({ 'setTimeout': setImmediate }).defer;
1446    */
1447   var runInContext = (function runInContext(context) {
1448     context = context == null ? root : _.defaults(root.Object(), context, _.pick(root, contextProps));
1449
1450     /** Built-in constructor references. */
1451     var Array = context.Array,
1452         Date = context.Date,
1453         Error = context.Error,
1454         Function = context.Function,
1455         Math = context.Math,
1456         Object = context.Object,
1457         RegExp = context.RegExp,
1458         String = context.String,
1459         TypeError = context.TypeError;
1460
1461     /** Used for built-in method references. */
1462     var arrayProto = Array.prototype,
1463         funcProto = Function.prototype,
1464         objectProto = Object.prototype;
1465
1466     /** Used to detect overreaching core-js shims. */
1467     var coreJsData = context['__core-js_shared__'];
1468
1469     /** Used to resolve the decompiled source of functions. */
1470     var funcToString = funcProto.toString;
1471
1472     /** Used to check objects for own properties. */
1473     var hasOwnProperty = objectProto.hasOwnProperty;
1474
1475     /** Used to generate unique IDs. */
1476     var idCounter = 0;
1477
1478     /** Used to detect methods masquerading as native. */
1479     var maskSrcKey = (function() {
1480       var uid = /[^.]+$/.exec(coreJsData && coreJsData.keys && coreJsData.keys.IE_PROTO || '');
1481       return uid ? ('Symbol(src)_1.' + uid) : '';
1482     }());
1483
1484     /**
1485      * Used to resolve the
1486      * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)
1487      * of values.
1488      */
1489     var nativeObjectToString = objectProto.toString;
1490
1491     /** Used to infer the `Object` constructor. */
1492     var objectCtorString = funcToString.call(Object);
1493
1494     /** Used to restore the original `_` reference in `_.noConflict`. */
1495     var oldDash = root._;
1496
1497     /** Used to detect if a method is native. */
1498     var reIsNative = RegExp('^' +
1499       funcToString.call(hasOwnProperty).replace(reRegExpChar, '\\$&')
1500       .replace(/hasOwnProperty|(function).*?(?=\\\()| for .+?(?=\\\])/g, '$1.*?') + '$'
1501     );
1502
1503     /** Built-in value references. */
1504     var Buffer = moduleExports ? context.Buffer : undefined,
1505         Symbol = context.Symbol,
1506         Uint8Array = context.Uint8Array,
1507         allocUnsafe = Buffer ? Buffer.allocUnsafe : undefined,
1508         getPrototype = overArg(Object.getPrototypeOf, Object),
1509         objectCreate = Object.create,
1510         propertyIsEnumerable = objectProto.propertyIsEnumerable,
1511         splice = arrayProto.splice,
1512         spreadableSymbol = Symbol ? Symbol.isConcatSpreadable : undefined,
1513         symIterator = Symbol ? Symbol.iterator : undefined,
1514         symToStringTag = Symbol ? Symbol.toStringTag : undefined;
1515
1516     var defineProperty = (function() {
1517       try {
1518         var func = getNative(Object, 'defineProperty');
1519         func({}, '', {});
1520         return func;
1521       } catch (e) {}
1522     }());
1523
1524     /** Mocked built-ins. */
1525     var ctxClearTimeout = context.clearTimeout !== root.clearTimeout && context.clearTimeout,
1526         ctxNow = Date && Date.now !== root.Date.now && Date.now,
1527         ctxSetTimeout = context.setTimeout !== root.setTimeout && context.setTimeout;
1528
1529     /* Built-in method references for those with the same name as other `lodash` methods. */
1530     var nativeCeil = Math.ceil,
1531         nativeFloor = Math.floor,
1532         nativeGetSymbols = Object.getOwnPropertySymbols,
1533         nativeIsBuffer = Buffer ? Buffer.isBuffer : undefined,
1534         nativeIsFinite = context.isFinite,
1535         nativeJoin = arrayProto.join,
1536         nativeKeys = overArg(Object.keys, Object),
1537         nativeMax = Math.max,
1538         nativeMin = Math.min,
1539         nativeNow = Date.now,
1540         nativeParseInt = context.parseInt,
1541         nativeRandom = Math.random,
1542         nativeReverse = arrayProto.reverse;
1543
1544     /* Built-in method references that are verified to be native. */
1545     var DataView = getNative(context, 'DataView'),
1546         Map = getNative(context, 'Map'),
1547         Promise = getNative(context, 'Promise'),
1548         Set = getNative(context, 'Set'),
1549         WeakMap = getNative(context, 'WeakMap'),
1550         nativeCreate = getNative(Object, 'create');
1551
1552     /** Used to store function metadata. */
1553     var metaMap = WeakMap && new WeakMap;
1554
1555     /** Used to lookup unminified function names. */
1556     var realNames = {};
1557
1558     /** Used to detect maps, sets, and weakmaps. */
1559     var dataViewCtorString = toSource(DataView),
1560         mapCtorString = toSource(Map),
1561         promiseCtorString = toSource(Promise),
1562         setCtorString = toSource(Set),
1563         weakMapCtorString = toSource(WeakMap);
1564
1565     /** Used to convert symbols to primitives and strings. */
1566     var symbolProto = Symbol ? Symbol.prototype : undefined,
1567         symbolValueOf = symbolProto ? symbolProto.valueOf : undefined,
1568         symbolToString = symbolProto ? symbolProto.toString : undefined;
1569
1570     /*------------------------------------------------------------------------*/
1571
1572     /**
1573      * Creates a `lodash` object which wraps `value` to enable implicit method
1574      * chain sequences. Methods that operate on and return arrays, collections,
1575      * and functions can be chained together. Methods that retrieve a single value
1576      * or may return a primitive value will automatically end the chain sequence
1577      * and return the unwrapped value. Otherwise, the value must be unwrapped
1578      * with `_#value`.
1579      *
1580      * Explicit chain sequences, which must be unwrapped with `_#value`, may be
1581      * enabled using `_.chain`.
1582      *
1583      * The execution of chained methods is lazy, that is, it's deferred until
1584      * `_#value` is implicitly or explicitly called.
1585      *
1586      * Lazy evaluation allows several methods to support shortcut fusion.
1587      * Shortcut fusion is an optimization to merge iteratee calls; this avoids
1588      * the creation of intermediate arrays and can greatly reduce the number of
1589      * iteratee executions. Sections of a chain sequence qualify for shortcut
1590      * fusion if the section is applied to an array of at least `200` elements
1591      * and any iteratees accept only one argument. The heuristic for whether a
1592      * section qualifies for shortcut fusion is subject to change.
1593      *
1594      * Chaining is supported in custom builds as long as the `_#value` method is
1595      * directly or indirectly included in the build.
1596      *
1597      * In addition to lodash methods, wrappers have `Array` and `String` methods.
1598      *
1599      * The wrapper `Array` methods are:
1600      * `concat`, `join`, `pop`, `push`, `shift`, `sort`, `splice`, and `unshift`
1601      *
1602      * The wrapper `String` methods are:
1603      * `replace` and `split`
1604      *
1605      * The wrapper methods that support shortcut fusion are:
1606      * `at`, `compact`, `drop`, `dropRight`, `dropWhile`, `filter`, `find`,
1607      * `findLast`, `head`, `initial`, `last`, `map`, `reject`, `reverse`, `slice`,
1608      * `tail`, `take`, `takeRight`, `takeRightWhile`, `takeWhile`, and `toArray`
1609      *
1610      * The chainable wrapper methods are:
1611      * `after`, `ary`, `assign`, `assignIn`, `assignInWith`, `assignWith`, `at`,
1612      * `before`, `bind`, `bindAll`, `bindKey`, `castArray`, `chain`, `chunk`,
1613      * `commit`, `compact`, `concat`, `conforms`, `constant`, `countBy`, `create`,
1614      * `curry`, `debounce`, `defaults`, `defaultsDeep`, `defer`, `delay`,
1615      * `difference`, `differenceBy`, `differenceWith`, `drop`, `dropRight`,
1616      * `dropRightWhile`, `dropWhile`, `extend`, `extendWith`, `fill`, `filter`,
1617      * `flatMap`, `flatMapDeep`, `flatMapDepth`, `flatten`, `flattenDeep`,
1618      * `flattenDepth`, `flip`, `flow`, `flowRight`, `fromPairs`, `functions`,
1619      * `functionsIn`, `groupBy`, `initial`, `intersection`, `intersectionBy`,
1620      * `intersectionWith`, `invert`, `invertBy`, `invokeMap`, `iteratee`, `keyBy`,
1621      * `keys`, `keysIn`, `map`, `mapKeys`, `mapValues`, `matches`, `matchesProperty`,
1622      * `memoize`, `merge`, `mergeWith`, `method`, `methodOf`, `mixin`, `negate`,
1623      * `nthArg`, `omit`, `omitBy`, `once`, `orderBy`, `over`, `overArgs`,
1624      * `overEvery`, `overSome`, `partial`, `partialRight`, `partition`, `pick`,
1625      * `pickBy`, `plant`, `property`, `propertyOf`, `pull`, `pullAll`, `pullAllBy`,
1626      * `pullAllWith`, `pullAt`, `push`, `range`, `rangeRight`, `rearg`, `reject`,
1627      * `remove`, `rest`, `reverse`, `sampleSize`, `set`, `setWith`, `shuffle`,
1628      * `slice`, `sort`, `sortBy`, `splice`, `spread`, `tail`, `take`, `takeRight`,
1629      * `takeRightWhile`, `takeWhile`, `tap`, `throttle`, `thru`, `toArray`,
1630      * `toPairs`, `toPairsIn`, `toPath`, `toPlainObject`, `transform`, `unary`,
1631      * `union`, `unionBy`, `unionWith`, `uniq`, `uniqBy`, `uniqWith`, `unset`,
1632      * `unshift`, `unzip`, `unzipWith`, `update`, `updateWith`, `values`,
1633      * `valuesIn`, `without`, `wrap`, `xor`, `xorBy`, `xorWith`, `zip`,
1634      * `zipObject`, `zipObjectDeep`, and `zipWith`
1635      *
1636      * The wrapper methods that are **not** chainable by default are:
1637      * `add`, `attempt`, `camelCase`, `capitalize`, `ceil`, `clamp`, `clone`,
1638      * `cloneDeep`, `cloneDeepWith`, `cloneWith`, `conformsTo`, `deburr`,
1639      * `defaultTo`, `divide`, `each`, `eachRight`, `endsWith`, `eq`, `escape`,
1640      * `escapeRegExp`, `every`, `find`, `findIndex`, `findKey`, `findLast`,
1641      * `findLastIndex`, `findLastKey`, `first`, `floor`, `forEach`, `forEachRight`,
1642      * `forIn`, `forInRight`, `forOwn`, `forOwnRight`, `get`, `gt`, `gte`, `has`,
1643      * `hasIn`, `head`, `identity`, `includes`, `indexOf`, `inRange`, `invoke`,
1644      * `isArguments`, `isArray`, `isArrayBuffer`, `isArrayLike`, `isArrayLikeObject`,
1645      * `isBoolean`, `isBuffer`, `isDate`, `isElement`, `isEmpty`, `isEqual`,
1646      * `isEqualWith`, `isError`, `isFinite`, `isFunction`, `isInteger`, `isLength`,
1647      * `isMap`, `isMatch`, `isMatchWith`, `isNaN`, `isNative`, `isNil`, `isNull`,
1648      * `isNumber`, `isObject`, `isObjectLike`, `isPlainObject`, `isRegExp`,
1649      * `isSafeInteger`, `isSet`, `isString`, `isUndefined`, `isTypedArray`,
1650      * `isWeakMap`, `isWeakSet`, `join`, `kebabCase`, `last`, `lastIndexOf`,
1651      * `lowerCase`, `lowerFirst`, `lt`, `lte`, `max`, `maxBy`, `mean`, `meanBy`,
1652      * `min`, `minBy`, `multiply`, `noConflict`, `noop`, `now`, `nth`, `pad`,
1653      * `padEnd`, `padStart`, `parseInt`, `pop`, `random`, `reduce`, `reduceRight`,
1654      * `repeat`, `result`, `round`, `runInContext`, `sample`, `shift`, `size`,
1655      * `snakeCase`, `some`, `sortedIndex`, `sortedIndexBy`, `sortedLastIndex`,
1656      * `sortedLastIndexBy`, `startCase`, `startsWith`, `stubArray`, `stubFalse`,
1657      * `stubObject`, `stubString`, `stubTrue`, `subtract`, `sum`, `sumBy`,
1658      * `template`, `times`, `toFinite`, `toInteger`, `toJSON`, `toLength`,
1659      * `toLower`, `toNumber`, `toSafeInteger`, `toString`, `toUpper`, `trim`,
1660      * `trimEnd`, `trimStart`, `truncate`, `unescape`, `uniqueId`, `upperCase`,
1661      * `upperFirst`, `value`, and `words`
1662      *
1663      * @name _
1664      * @constructor
1665      * @category Seq
1666      * @param {*} value The value to wrap in a `lodash` instance.
1667      * @returns {Object} Returns the new `lodash` wrapper instance.
1668      * @example
1669      *
1670      * function square(n) {
1671      *   return n * n;
1672      * }
1673      *
1674      * var wrapped = _([1, 2, 3]);
1675      *
1676      * // Returns an unwrapped value.
1677      * wrapped.reduce(_.add);
1678      * // => 6
1679      *
1680      * // Returns a wrapped value.
1681      * var squares = wrapped.map(square);
1682      *
1683      * _.isArray(squares);
1684      * // => false
1685      *
1686      * _.isArray(squares.value());
1687      * // => true
1688      */
1689     function lodash(value) {
1690       if (isObjectLike(value) && !isArray(value) && !(value instanceof LazyWrapper)) {
1691         if (value instanceof LodashWrapper) {
1692           return value;
1693         }
1694         if (hasOwnProperty.call(value, '__wrapped__')) {
1695           return wrapperClone(value);
1696         }
1697       }
1698       return new LodashWrapper(value);
1699     }
1700
1701     /**
1702      * The base implementation of `_.create` without support for assigning
1703      * properties to the created object.
1704      *
1705      * @private
1706      * @param {Object} proto The object to inherit from.
1707      * @returns {Object} Returns the new object.
1708      */
1709     var baseCreate = (function() {
1710       function object() {}
1711       return function(proto) {
1712         if (!isObject(proto)) {
1713           return {};
1714         }
1715         if (objectCreate) {
1716           return objectCreate(proto);
1717         }
1718         object.prototype = proto;
1719         var result = new object;
1720         object.prototype = undefined;
1721         return result;
1722       };
1723     }());
1724
1725     /**
1726      * The function whose prototype chain sequence wrappers inherit from.
1727      *
1728      * @private
1729      */
1730     function baseLodash() {
1731       // No operation performed.
1732     }
1733
1734     /**
1735      * The base constructor for creating `lodash` wrapper objects.
1736      *
1737      * @private
1738      * @param {*} value The value to wrap.
1739      * @param {boolean} [chainAll] Enable explicit method chain sequences.
1740      */
1741     function LodashWrapper(value, chainAll) {
1742       this.__wrapped__ = value;
1743       this.__actions__ = [];
1744       this.__chain__ = !!chainAll;
1745       this.__index__ = 0;
1746       this.__values__ = undefined;
1747     }
1748
1749     /**
1750      * By default, the template delimiters used by lodash are like those in
1751      * embedded Ruby (ERB). Change the following template settings to use
1752      * alternative delimiters.
1753      *
1754      * @static
1755      * @memberOf _
1756      * @type {Object}
1757      */
1758     lodash.templateSettings = {
1759
1760       /**
1761        * Used to detect `data` property values to be HTML-escaped.
1762        *
1763        * @memberOf _.templateSettings
1764        * @type {RegExp}
1765        */
1766       'escape': reEscape,
1767
1768       /**
1769        * Used to detect code to be evaluated.
1770        *
1771        * @memberOf _.templateSettings
1772        * @type {RegExp}
1773        */
1774       'evaluate': reEvaluate,
1775
1776       /**
1777        * Used to detect `data` property values to inject.
1778        *
1779        * @memberOf _.templateSettings
1780        * @type {RegExp}
1781        */
1782       'interpolate': reInterpolate,
1783
1784       /**
1785        * Used to reference the data object in the template text.
1786        *
1787        * @memberOf _.templateSettings
1788        * @type {string}
1789        */
1790       'variable': '',
1791
1792       /**
1793        * Used to import variables into the compiled template.
1794        *
1795        * @memberOf _.templateSettings
1796        * @type {Object}
1797        */
1798       'imports': {
1799
1800         /**
1801          * A reference to the `lodash` function.
1802          *
1803          * @memberOf _.templateSettings.imports
1804          * @type {Function}
1805          */
1806         '_': lodash
1807       }
1808     };
1809
1810     // Ensure wrappers are instances of `baseLodash`.
1811     lodash.prototype = baseLodash.prototype;
1812     lodash.prototype.constructor = lodash;
1813
1814     LodashWrapper.prototype = baseCreate(baseLodash.prototype);
1815     LodashWrapper.prototype.constructor = LodashWrapper;
1816
1817     /*------------------------------------------------------------------------*/
1818
1819     /**
1820      * Creates a lazy wrapper object which wraps `value` to enable lazy evaluation.
1821      *
1822      * @private
1823      * @constructor
1824      * @param {*} value The value to wrap.
1825      */
1826     function LazyWrapper(value) {
1827       this.__wrapped__ = value;
1828       this.__actions__ = [];
1829       this.__dir__ = 1;
1830       this.__filtered__ = false;
1831       this.__iteratees__ = [];
1832       this.__takeCount__ = MAX_ARRAY_LENGTH;
1833       this.__views__ = [];
1834     }
1835
1836     /**
1837      * Creates a clone of the lazy wrapper object.
1838      *
1839      * @private
1840      * @name clone
1841      * @memberOf LazyWrapper
1842      * @returns {Object} Returns the cloned `LazyWrapper` object.
1843      */
1844     function lazyClone() {
1845       var result = new LazyWrapper(this.__wrapped__);
1846       result.__actions__ = copyArray(this.__actions__);
1847       result.__dir__ = this.__dir__;
1848       result.__filtered__ = this.__filtered__;
1849       result.__iteratees__ = copyArray(this.__iteratees__);
1850       result.__takeCount__ = this.__takeCount__;
1851       result.__views__ = copyArray(this.__views__);
1852       return result;
1853     }
1854
1855     /**
1856      * Reverses the direction of lazy iteration.
1857      *
1858      * @private
1859      * @name reverse
1860      * @memberOf LazyWrapper
1861      * @returns {Object} Returns the new reversed `LazyWrapper` object.
1862      */
1863     function lazyReverse() {
1864       if (this.__filtered__) {
1865         var result = new LazyWrapper(this);
1866         result.__dir__ = -1;
1867         result.__filtered__ = true;
1868       } else {
1869         result = this.clone();
1870         result.__dir__ *= -1;
1871       }
1872       return result;
1873     }
1874
1875     /**
1876      * Extracts the unwrapped value from its lazy wrapper.
1877      *
1878      * @private
1879      * @name value
1880      * @memberOf LazyWrapper
1881      * @returns {*} Returns the unwrapped value.
1882      */
1883     function lazyValue() {
1884       var array = this.__wrapped__.value(),
1885           dir = this.__dir__,
1886           isArr = isArray(array),
1887           isRight = dir < 0,
1888           arrLength = isArr ? array.length : 0,
1889           view = getView(0, arrLength, this.__views__),
1890           start = view.start,
1891           end = view.end,
1892           length = end - start,
1893           index = isRight ? end : (start - 1),
1894           iteratees = this.__iteratees__,
1895           iterLength = iteratees.length,
1896           resIndex = 0,
1897           takeCount = nativeMin(length, this.__takeCount__);
1898
1899       if (!isArr || arrLength < LARGE_ARRAY_SIZE ||
1900           (arrLength == length && takeCount == length)) {
1901         return baseWrapperValue(array, this.__actions__);
1902       }
1903       var result = [];
1904
1905       outer:
1906       while (length-- && resIndex < takeCount) {
1907         index += dir;
1908
1909         var iterIndex = -1,
1910             value = array[index];
1911
1912         while (++iterIndex < iterLength) {
1913           var data = iteratees[iterIndex],
1914               iteratee = data.iteratee,
1915               type = data.type,
1916               computed = iteratee(value);
1917
1918           if (type == LAZY_MAP_FLAG) {
1919             value = computed;
1920           } else if (!computed) {
1921             if (type == LAZY_FILTER_FLAG) {
1922               continue outer;
1923             } else {
1924               break outer;
1925             }
1926           }
1927         }
1928         result[resIndex++] = value;
1929       }
1930       return result;
1931     }
1932
1933     // Ensure `LazyWrapper` is an instance of `baseLodash`.
1934     LazyWrapper.prototype = baseCreate(baseLodash.prototype);
1935     LazyWrapper.prototype.constructor = LazyWrapper;
1936
1937     /*------------------------------------------------------------------------*/
1938
1939     /**
1940      * Creates a hash object.
1941      *
1942      * @private
1943      * @constructor
1944      * @param {Array} [entries] The key-value pairs to cache.
1945      */
1946     function Hash(entries) {
1947       var index = -1,
1948           length = entries == null ? 0 : entries.length;
1949
1950       this.clear();
1951       while (++index < length) {
1952         var entry = entries[index];
1953         this.set(entry[0], entry[1]);
1954       }
1955     }
1956
1957     /**
1958      * Removes all key-value entries from the hash.
1959      *
1960      * @private
1961      * @name clear
1962      * @memberOf Hash
1963      */
1964     function hashClear() {
1965       this.__data__ = nativeCreate ? nativeCreate(null) : {};
1966       this.size = 0;
1967     }
1968
1969     /**
1970      * Removes `key` and its value from the hash.
1971      *
1972      * @private
1973      * @name delete
1974      * @memberOf Hash
1975      * @param {Object} hash The hash to modify.
1976      * @param {string} key The key of the value to remove.
1977      * @returns {boolean} Returns `true` if the entry was removed, else `false`.
1978      */
1979     function hashDelete(key) {
1980       var result = this.has(key) && delete this.__data__[key];
1981       this.size -= result ? 1 : 0;
1982       return result;
1983     }
1984
1985     /**
1986      * Gets the hash value for `key`.
1987      *
1988      * @private
1989      * @name get
1990      * @memberOf Hash
1991      * @param {string} key The key of the value to get.
1992      * @returns {*} Returns the entry value.
1993      */
1994     function hashGet(key) {
1995       var data = this.__data__;
1996       if (nativeCreate) {
1997         var result = data[key];
1998         return result === HASH_UNDEFINED ? undefined : result;
1999       }
2000       return hasOwnProperty.call(data, key) ? data[key] : undefined;
2001     }
2002
2003     /**
2004      * Checks if a hash value for `key` exists.
2005      *
2006      * @private
2007      * @name has
2008      * @memberOf Hash
2009      * @param {string} key The key of the entry to check.
2010      * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
2011      */
2012     function hashHas(key) {
2013       var data = this.__data__;
2014       return nativeCreate ? data[key] !== undefined : hasOwnProperty.call(data, key);
2015     }
2016
2017     /**
2018      * Sets the hash `key` to `value`.
2019      *
2020      * @private
2021      * @name set
2022      * @memberOf Hash
2023      * @param {string} key The key of the value to set.
2024      * @param {*} value The value to set.
2025      * @returns {Object} Returns the hash instance.
2026      */
2027     function hashSet(key, value) {
2028       var data = this.__data__;
2029       this.size += this.has(key) ? 0 : 1;
2030       data[key] = (nativeCreate && value === undefined) ? HASH_UNDEFINED : value;
2031       return this;
2032     }
2033
2034     // Add methods to `Hash`.
2035     Hash.prototype.clear = hashClear;
2036     Hash.prototype['delete'] = hashDelete;
2037     Hash.prototype.get = hashGet;
2038     Hash.prototype.has = hashHas;
2039     Hash.prototype.set = hashSet;
2040
2041     /*------------------------------------------------------------------------*/
2042
2043     /**
2044      * Creates an list cache object.
2045      *
2046      * @private
2047      * @constructor
2048      * @param {Array} [entries] The key-value pairs to cache.
2049      */
2050     function ListCache(entries) {
2051       var index = -1,
2052           length = entries == null ? 0 : entries.length;
2053
2054       this.clear();
2055       while (++index < length) {
2056         var entry = entries[index];
2057         this.set(entry[0], entry[1]);
2058       }
2059     }
2060
2061     /**
2062      * Removes all key-value entries from the list cache.
2063      *
2064      * @private
2065      * @name clear
2066      * @memberOf ListCache
2067      */
2068     function listCacheClear() {
2069       this.__data__ = [];
2070       this.size = 0;
2071     }
2072
2073     /**
2074      * Removes `key` and its value from the list cache.
2075      *
2076      * @private
2077      * @name delete
2078      * @memberOf ListCache
2079      * @param {string} key The key of the value to remove.
2080      * @returns {boolean} Returns `true` if the entry was removed, else `false`.
2081      */
2082     function listCacheDelete(key) {
2083       var data = this.__data__,
2084           index = assocIndexOf(data, key);
2085
2086       if (index < 0) {
2087         return false;
2088       }
2089       var lastIndex = data.length - 1;
2090       if (index == lastIndex) {
2091         data.pop();
2092       } else {
2093         splice.call(data, index, 1);
2094       }
2095       --this.size;
2096       return true;
2097     }
2098
2099     /**
2100      * Gets the list cache value for `key`.
2101      *
2102      * @private
2103      * @name get
2104      * @memberOf ListCache
2105      * @param {string} key The key of the value to get.
2106      * @returns {*} Returns the entry value.
2107      */
2108     function listCacheGet(key) {
2109       var data = this.__data__,
2110           index = assocIndexOf(data, key);
2111
2112       return index < 0 ? undefined : data[index][1];
2113     }
2114
2115     /**
2116      * Checks if a list cache value for `key` exists.
2117      *
2118      * @private
2119      * @name has
2120      * @memberOf ListCache
2121      * @param {string} key The key of the entry to check.
2122      * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
2123      */
2124     function listCacheHas(key) {
2125       return assocIndexOf(this.__data__, key) > -1;
2126     }
2127
2128     /**
2129      * Sets the list cache `key` to `value`.
2130      *
2131      * @private
2132      * @name set
2133      * @memberOf ListCache
2134      * @param {string} key The key of the value to set.
2135      * @param {*} value The value to set.
2136      * @returns {Object} Returns the list cache instance.
2137      */
2138     function listCacheSet(key, value) {
2139       var data = this.__data__,
2140           index = assocIndexOf(data, key);
2141
2142       if (index < 0) {
2143         ++this.size;
2144         data.push([key, value]);
2145       } else {
2146         data[index][1] = value;
2147       }
2148       return this;
2149     }
2150
2151     // Add methods to `ListCache`.
2152     ListCache.prototype.clear = listCacheClear;
2153     ListCache.prototype['delete'] = listCacheDelete;
2154     ListCache.prototype.get = listCacheGet;
2155     ListCache.prototype.has = listCacheHas;
2156     ListCache.prototype.set = listCacheSet;
2157
2158     /*------------------------------------------------------------------------*/
2159
2160     /**
2161      * Creates a map cache object to store key-value pairs.
2162      *
2163      * @private
2164      * @constructor
2165      * @param {Array} [entries] The key-value pairs to cache.
2166      */
2167     function MapCache(entries) {
2168       var index = -1,
2169           length = entries == null ? 0 : entries.length;
2170
2171       this.clear();
2172       while (++index < length) {
2173         var entry = entries[index];
2174         this.set(entry[0], entry[1]);
2175       }
2176     }
2177
2178     /**
2179      * Removes all key-value entries from the map.
2180      *
2181      * @private
2182      * @name clear
2183      * @memberOf MapCache
2184      */
2185     function mapCacheClear() {
2186       this.size = 0;
2187       this.__data__ = {
2188         'hash': new Hash,
2189         'map': new (Map || ListCache),
2190         'string': new Hash
2191       };
2192     }
2193
2194     /**
2195      * Removes `key` and its value from the map.
2196      *
2197      * @private
2198      * @name delete
2199      * @memberOf MapCache
2200      * @param {string} key The key of the value to remove.
2201      * @returns {boolean} Returns `true` if the entry was removed, else `false`.
2202      */
2203     function mapCacheDelete(key) {
2204       var result = getMapData(this, key)['delete'](key);
2205       this.size -= result ? 1 : 0;
2206       return result;
2207     }
2208
2209     /**
2210      * Gets the map value for `key`.
2211      *
2212      * @private
2213      * @name get
2214      * @memberOf MapCache
2215      * @param {string} key The key of the value to get.
2216      * @returns {*} Returns the entry value.
2217      */
2218     function mapCacheGet(key) {
2219       return getMapData(this, key).get(key);
2220     }
2221
2222     /**
2223      * Checks if a map value for `key` exists.
2224      *
2225      * @private
2226      * @name has
2227      * @memberOf MapCache
2228      * @param {string} key The key of the entry to check.
2229      * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
2230      */
2231     function mapCacheHas(key) {
2232       return getMapData(this, key).has(key);
2233     }
2234
2235     /**
2236      * Sets the map `key` to `value`.
2237      *
2238      * @private
2239      * @name set
2240      * @memberOf MapCache
2241      * @param {string} key The key of the value to set.
2242      * @param {*} value The value to set.
2243      * @returns {Object} Returns the map cache instance.
2244      */
2245     function mapCacheSet(key, value) {
2246       var data = getMapData(this, key),
2247           size = data.size;
2248
2249       data.set(key, value);
2250       this.size += data.size == size ? 0 : 1;
2251       return this;
2252     }
2253
2254     // Add methods to `MapCache`.
2255     MapCache.prototype.clear = mapCacheClear;
2256     MapCache.prototype['delete'] = mapCacheDelete;
2257     MapCache.prototype.get = mapCacheGet;
2258     MapCache.prototype.has = mapCacheHas;
2259     MapCache.prototype.set = mapCacheSet;
2260
2261     /*------------------------------------------------------------------------*/
2262
2263     /**
2264      *
2265      * Creates an array cache object to store unique values.
2266      *
2267      * @private
2268      * @constructor
2269      * @param {Array} [values] The values to cache.
2270      */
2271     function SetCache(values) {
2272       var index = -1,
2273           length = values == null ? 0 : values.length;
2274
2275       this.__data__ = new MapCache;
2276       while (++index < length) {
2277         this.add(values[index]);
2278       }
2279     }
2280
2281     /**
2282      * Adds `value` to the array cache.
2283      *
2284      * @private
2285      * @name add
2286      * @memberOf SetCache
2287      * @alias push
2288      * @param {*} value The value to cache.
2289      * @returns {Object} Returns the cache instance.
2290      */
2291     function setCacheAdd(value) {
2292       this.__data__.set(value, HASH_UNDEFINED);
2293       return this;
2294     }
2295
2296     /**
2297      * Checks if `value` is in the array cache.
2298      *
2299      * @private
2300      * @name has
2301      * @memberOf SetCache
2302      * @param {*} value The value to search for.
2303      * @returns {number} Returns `true` if `value` is found, else `false`.
2304      */
2305     function setCacheHas(value) {
2306       return this.__data__.has(value);
2307     }
2308
2309     // Add methods to `SetCache`.
2310     SetCache.prototype.add = SetCache.prototype.push = setCacheAdd;
2311     SetCache.prototype.has = setCacheHas;
2312
2313     /*------------------------------------------------------------------------*/
2314
2315     /**
2316      * Creates a stack cache object to store key-value pairs.
2317      *
2318      * @private
2319      * @constructor
2320      * @param {Array} [entries] The key-value pairs to cache.
2321      */
2322     function Stack(entries) {
2323       var data = this.__data__ = new ListCache(entries);
2324       this.size = data.size;
2325     }
2326
2327     /**
2328      * Removes all key-value entries from the stack.
2329      *
2330      * @private
2331      * @name clear
2332      * @memberOf Stack
2333      */
2334     function stackClear() {
2335       this.__data__ = new ListCache;
2336       this.size = 0;
2337     }
2338
2339     /**
2340      * Removes `key` and its value from the stack.
2341      *
2342      * @private
2343      * @name delete
2344      * @memberOf Stack
2345      * @param {string} key The key of the value to remove.
2346      * @returns {boolean} Returns `true` if the entry was removed, else `false`.
2347      */
2348     function stackDelete(key) {
2349       var data = this.__data__,
2350           result = data['delete'](key);
2351
2352       this.size = data.size;
2353       return result;
2354     }
2355
2356     /**
2357      * Gets the stack value for `key`.
2358      *
2359      * @private
2360      * @name get
2361      * @memberOf Stack
2362      * @param {string} key The key of the value to get.
2363      * @returns {*} Returns the entry value.
2364      */
2365     function stackGet(key) {
2366       return this.__data__.get(key);
2367     }
2368
2369     /**
2370      * Checks if a stack value for `key` exists.
2371      *
2372      * @private
2373      * @name has
2374      * @memberOf Stack
2375      * @param {string} key The key of the entry to check.
2376      * @returns {boolean} Returns `true` if an entry for `key` exists, else `false`.
2377      */
2378     function stackHas(key) {
2379       return this.__data__.has(key);
2380     }
2381
2382     /**
2383      * Sets the stack `key` to `value`.
2384      *
2385      * @private
2386      * @name set
2387      * @memberOf Stack
2388      * @param {string} key The key of the value to set.
2389      * @param {*} value The value to set.
2390      * @returns {Object} Returns the stack cache instance.
2391      */
2392     function stackSet(key, value) {
2393       var data = this.__data__;
2394       if (data instanceof ListCache) {
2395         var pairs = data.__data__;
2396         if (!Map || (pairs.length < LARGE_ARRAY_SIZE - 1)) {
2397           pairs.push([key, value]);
2398           this.size = ++data.size;
2399           return this;
2400         }
2401         data = this.__data__ = new MapCache(pairs);
2402       }
2403       data.set(key, value);
2404       this.size = data.size;
2405       return this;
2406     }
2407
2408     // Add methods to `Stack`.
2409     Stack.prototype.clear = stackClear;
2410     Stack.prototype['delete'] = stackDelete;
2411     Stack.prototype.get = stackGet;
2412     Stack.prototype.has = stackHas;
2413     Stack.prototype.set = stackSet;
2414
2415     /*------------------------------------------------------------------------*/
2416
2417     /**
2418      * Creates an array of the enumerable property names of the array-like `value`.
2419      *
2420      * @private
2421      * @param {*} value The value to query.
2422      * @param {boolean} inherited Specify returning inherited property names.
2423      * @returns {Array} Returns the array of property names.
2424      */
2425     function arrayLikeKeys(value, inherited) {
2426       var isArr = isArray(value),
2427           isArg = !isArr && isArguments(value),
2428           isBuff = !isArr && !isArg && isBuffer(value),
2429           isType = !isArr && !isArg && !isBuff && isTypedArray(value),
2430           skipIndexes = isArr || isArg || isBuff || isType,
2431           result = skipIndexes ? baseTimes(value.length, String) : [],
2432           length = result.length;
2433
2434       for (var key in value) {
2435         if ((inherited || hasOwnProperty.call(value, key)) &&
2436             !(skipIndexes && (
2437                // Safari 9 has enumerable `arguments.length` in strict mode.
2438                key == 'length' ||
2439                // Node.js 0.10 has enumerable non-index properties on buffers.
2440                (isBuff && (key == 'offset' || key == 'parent')) ||
2441                // PhantomJS 2 has enumerable non-index properties on typed arrays.
2442                (isType && (key == 'buffer' || key == 'byteLength' || key == 'byteOffset')) ||
2443                // Skip index properties.
2444                isIndex(key, length)
2445             ))) {
2446           result.push(key);
2447         }
2448       }
2449       return result;
2450     }
2451
2452     /**
2453      * A specialized version of `_.sample` for arrays.
2454      *
2455      * @private
2456      * @param {Array} array The array to sample.
2457      * @returns {*} Returns the random element.
2458      */
2459     function arraySample(array) {
2460       var length = array.length;
2461       return length ? array[baseRandom(0, length - 1)] : undefined;
2462     }
2463
2464     /**
2465      * A specialized version of `_.sampleSize` for arrays.
2466      *
2467      * @private
2468      * @param {Array} array The array to sample.
2469      * @param {number} n The number of elements to sample.
2470      * @returns {Array} Returns the random elements.
2471      */
2472     function arraySampleSize(array, n) {
2473       return shuffleSelf(copyArray(array), baseClamp(n, 0, array.length));
2474     }
2475
2476     /**
2477      * A specialized version of `_.shuffle` for arrays.
2478      *
2479      * @private
2480      * @param {Array} array The array to shuffle.
2481      * @returns {Array} Returns the new shuffled array.
2482      */
2483     function arrayShuffle(array) {
2484       return shuffleSelf(copyArray(array));
2485     }
2486
2487     /**
2488      * Used by `_.defaults` to customize its `_.assignIn` use.
2489      *
2490      * @private
2491      * @param {*} objValue The destination value.
2492      * @param {*} srcValue The source value.
2493      * @param {string} key The key of the property to assign.
2494      * @param {Object} object The parent object of `objValue`.
2495      * @returns {*} Returns the value to assign.
2496      */
2497     function assignInDefaults(objValue, srcValue, key, object) {
2498       if (objValue === undefined ||
2499           (eq(objValue, objectProto[key]) && !hasOwnProperty.call(object, key))) {
2500         return srcValue;
2501       }
2502       return objValue;
2503     }
2504
2505     /**
2506      * This function is like `assignValue` except that it doesn't assign
2507      * `undefined` values.
2508      *
2509      * @private
2510      * @param {Object} object The object to modify.
2511      * @param {string} key The key of the property to assign.
2512      * @param {*} value The value to assign.
2513      */
2514     function assignMergeValue(object, key, value) {
2515       if ((value !== undefined && !eq(object[key], value)) ||
2516           (value === undefined && !(key in object))) {
2517         baseAssignValue(object, key, value);
2518       }
2519     }
2520
2521     /**
2522      * Assigns `value` to `key` of `object` if the existing value is not equivalent
2523      * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
2524      * for equality comparisons.
2525      *
2526      * @private
2527      * @param {Object} object The object to modify.
2528      * @param {string} key The key of the property to assign.
2529      * @param {*} value The value to assign.
2530      */
2531     function assignValue(object, key, value) {
2532       var objValue = object[key];
2533       if (!(hasOwnProperty.call(object, key) && eq(objValue, value)) ||
2534           (value === undefined && !(key in object))) {
2535         baseAssignValue(object, key, value);
2536       }
2537     }
2538
2539     /**
2540      * Gets the index at which the `key` is found in `array` of key-value pairs.
2541      *
2542      * @private
2543      * @param {Array} array The array to inspect.
2544      * @param {*} key The key to search for.
2545      * @returns {number} Returns the index of the matched value, else `-1`.
2546      */
2547     function assocIndexOf(array, key) {
2548       var length = array.length;
2549       while (length--) {
2550         if (eq(array[length][0], key)) {
2551           return length;
2552         }
2553       }
2554       return -1;
2555     }
2556
2557     /**
2558      * Aggregates elements of `collection` on `accumulator` with keys transformed
2559      * by `iteratee` and values set by `setter`.
2560      *
2561      * @private
2562      * @param {Array|Object} collection The collection to iterate over.
2563      * @param {Function} setter The function to set `accumulator` values.
2564      * @param {Function} iteratee The iteratee to transform keys.
2565      * @param {Object} accumulator The initial aggregated object.
2566      * @returns {Function} Returns `accumulator`.
2567      */
2568     function baseAggregator(collection, setter, iteratee, accumulator) {
2569       baseEach(collection, function(value, key, collection) {
2570         setter(accumulator, value, iteratee(value), collection);
2571       });
2572       return accumulator;
2573     }
2574
2575     /**
2576      * The base implementation of `_.assign` without support for multiple sources
2577      * or `customizer` functions.
2578      *
2579      * @private
2580      * @param {Object} object The destination object.
2581      * @param {Object} source The source object.
2582      * @returns {Object} Returns `object`.
2583      */
2584     function baseAssign(object, source) {
2585       return object && copyObject(source, keys(source), object);
2586     }
2587
2588     /**
2589      * The base implementation of `_.assignIn` without support for multiple sources
2590      * or `customizer` functions.
2591      *
2592      * @private
2593      * @param {Object} object The destination object.
2594      * @param {Object} source The source object.
2595      * @returns {Object} Returns `object`.
2596      */
2597     function baseAssignIn(object, source) {
2598       return object && copyObject(source, keysIn(source), object);
2599     }
2600
2601     /**
2602      * The base implementation of `assignValue` and `assignMergeValue` without
2603      * value checks.
2604      *
2605      * @private
2606      * @param {Object} object The object to modify.
2607      * @param {string} key The key of the property to assign.
2608      * @param {*} value The value to assign.
2609      */
2610     function baseAssignValue(object, key, value) {
2611       if (key == '__proto__' && defineProperty) {
2612         defineProperty(object, key, {
2613           'configurable': true,
2614           'enumerable': true,
2615           'value': value,
2616           'writable': true
2617         });
2618       } else {
2619         object[key] = value;
2620       }
2621     }
2622
2623     /**
2624      * The base implementation of `_.at` without support for individual paths.
2625      *
2626      * @private
2627      * @param {Object} object The object to iterate over.
2628      * @param {string[]} paths The property paths to pick.
2629      * @returns {Array} Returns the picked elements.
2630      */
2631     function baseAt(object, paths) {
2632       var index = -1,
2633           length = paths.length,
2634           result = Array(length),
2635           skip = object == null;
2636
2637       while (++index < length) {
2638         result[index] = skip ? undefined : get(object, paths[index]);
2639       }
2640       return result;
2641     }
2642
2643     /**
2644      * The base implementation of `_.clamp` which doesn't coerce arguments.
2645      *
2646      * @private
2647      * @param {number} number The number to clamp.
2648      * @param {number} [lower] The lower bound.
2649      * @param {number} upper The upper bound.
2650      * @returns {number} Returns the clamped number.
2651      */
2652     function baseClamp(number, lower, upper) {
2653       if (number === number) {
2654         if (upper !== undefined) {
2655           number = number <= upper ? number : upper;
2656         }
2657         if (lower !== undefined) {
2658           number = number >= lower ? number : lower;
2659         }
2660       }
2661       return number;
2662     }
2663
2664     /**
2665      * The base implementation of `_.clone` and `_.cloneDeep` which tracks
2666      * traversed objects.
2667      *
2668      * @private
2669      * @param {*} value The value to clone.
2670      * @param {boolean} bitmask The bitmask flags.
2671      *  1 - Deep clone
2672      *  2 - Flatten inherited properties
2673      *  4 - Clone symbols
2674      * @param {Function} [customizer] The function to customize cloning.
2675      * @param {string} [key] The key of `value`.
2676      * @param {Object} [object] The parent object of `value`.
2677      * @param {Object} [stack] Tracks traversed objects and their clone counterparts.
2678      * @returns {*} Returns the cloned value.
2679      */
2680     function baseClone(value, bitmask, customizer, key, object, stack) {
2681       var result,
2682           isDeep = bitmask & CLONE_DEEP_FLAG,
2683           isFlat = bitmask & CLONE_FLAT_FLAG,
2684           isFull = bitmask & CLONE_SYMBOLS_FLAG;
2685
2686       if (customizer) {
2687         result = object ? customizer(value, key, object, stack) : customizer(value);
2688       }
2689       if (result !== undefined) {
2690         return result;
2691       }
2692       if (!isObject(value)) {
2693         return value;
2694       }
2695       var isArr = isArray(value);
2696       if (isArr) {
2697         result = initCloneArray(value);
2698         if (!isDeep) {
2699           return copyArray(value, result);
2700         }
2701       } else {
2702         var tag = getTag(value),
2703             isFunc = tag == funcTag || tag == genTag;
2704
2705         if (isBuffer(value)) {
2706           return cloneBuffer(value, isDeep);
2707         }
2708         if (tag == objectTag || tag == argsTag || (isFunc && !object)) {
2709           result = (isFlat || isFunc) ? {} : initCloneObject(value);
2710           if (!isDeep) {
2711             return isFlat
2712               ? copySymbolsIn(value, baseAssignIn(result, value))
2713               : copySymbols(value, baseAssign(result, value));
2714           }
2715         } else {
2716           if (!cloneableTags[tag]) {
2717             return object ? value : {};
2718           }
2719           result = initCloneByTag(value, tag, baseClone, isDeep);
2720         }
2721       }
2722       // Check for circular references and return its corresponding clone.
2723       stack || (stack = new Stack);
2724       var stacked = stack.get(value);
2725       if (stacked) {
2726         return stacked;
2727       }
2728       stack.set(value, result);
2729
2730       var keysFunc = isFull
2731         ? (isFlat ? getAllKeysIn : getAllKeys)
2732         : (isFlat ? keysIn : keys);
2733
2734       var props = isArr ? undefined : keysFunc(value);
2735       arrayEach(props || value, function(subValue, key) {
2736         if (props) {
2737           key = subValue;
2738           subValue = value[key];
2739         }
2740         // Recursively populate clone (susceptible to call stack limits).
2741         assignValue(result, key, baseClone(subValue, bitmask, customizer, key, value, stack));
2742       });
2743       return result;
2744     }
2745
2746     /**
2747      * The base implementation of `_.conforms` which doesn't clone `source`.
2748      *
2749      * @private
2750      * @param {Object} source The object of property predicates to conform to.
2751      * @returns {Function} Returns the new spec function.
2752      */
2753     function baseConforms(source) {
2754       var props = keys(source);
2755       return function(object) {
2756         return baseConformsTo(object, source, props);
2757       };
2758     }
2759
2760     /**
2761      * The base implementation of `_.conformsTo` which accepts `props` to check.
2762      *
2763      * @private
2764      * @param {Object} object The object to inspect.
2765      * @param {Object} source The object of property predicates to conform to.
2766      * @returns {boolean} Returns `true` if `object` conforms, else `false`.
2767      */
2768     function baseConformsTo(object, source, props) {
2769       var length = props.length;
2770       if (object == null) {
2771         return !length;
2772       }
2773       object = Object(object);
2774       while (length--) {
2775         var key = props[length],
2776             predicate = source[key],
2777             value = object[key];
2778
2779         if ((value === undefined && !(key in object)) || !predicate(value)) {
2780           return false;
2781         }
2782       }
2783       return true;
2784     }
2785
2786     /**
2787      * The base implementation of `_.delay` and `_.defer` which accepts `args`
2788      * to provide to `func`.
2789      *
2790      * @private
2791      * @param {Function} func The function to delay.
2792      * @param {number} wait The number of milliseconds to delay invocation.
2793      * @param {Array} args The arguments to provide to `func`.
2794      * @returns {number|Object} Returns the timer id or timeout object.
2795      */
2796     function baseDelay(func, wait, args) {
2797       if (typeof func != 'function') {
2798         throw new TypeError(FUNC_ERROR_TEXT);
2799       }
2800       return setTimeout(function() { func.apply(undefined, args); }, wait);
2801     }
2802
2803     /**
2804      * The base implementation of methods like `_.difference` without support
2805      * for excluding multiple arrays or iteratee shorthands.
2806      *
2807      * @private
2808      * @param {Array} array The array to inspect.
2809      * @param {Array} values The values to exclude.
2810      * @param {Function} [iteratee] The iteratee invoked per element.
2811      * @param {Function} [comparator] The comparator invoked per element.
2812      * @returns {Array} Returns the new array of filtered values.
2813      */
2814     function baseDifference(array, values, iteratee, comparator) {
2815       var index = -1,
2816           includes = arrayIncludes,
2817           isCommon = true,
2818           length = array.length,
2819           result = [],
2820           valuesLength = values.length;
2821
2822       if (!length) {
2823         return result;
2824       }
2825       if (iteratee) {
2826         values = arrayMap(values, baseUnary(iteratee));
2827       }
2828       if (comparator) {
2829         includes = arrayIncludesWith;
2830         isCommon = false;
2831       }
2832       else if (values.length >= LARGE_ARRAY_SIZE) {
2833         includes = cacheHas;
2834         isCommon = false;
2835         values = new SetCache(values);
2836       }
2837       outer:
2838       while (++index < length) {
2839         var value = array[index],
2840             computed = iteratee == null ? value : iteratee(value);
2841
2842         value = (comparator || value !== 0) ? value : 0;
2843         if (isCommon && computed === computed) {
2844           var valuesIndex = valuesLength;
2845           while (valuesIndex--) {
2846             if (values[valuesIndex] === computed) {
2847               continue outer;
2848             }
2849           }
2850           result.push(value);
2851         }
2852         else if (!includes(values, computed, comparator)) {
2853           result.push(value);
2854         }
2855       }
2856       return result;
2857     }
2858
2859     /**
2860      * The base implementation of `_.forEach` without support for iteratee shorthands.
2861      *
2862      * @private
2863      * @param {Array|Object} collection The collection to iterate over.
2864      * @param {Function} iteratee The function invoked per iteration.
2865      * @returns {Array|Object} Returns `collection`.
2866      */
2867     var baseEach = createBaseEach(baseForOwn);
2868
2869     /**
2870      * The base implementation of `_.forEachRight` without support for iteratee shorthands.
2871      *
2872      * @private
2873      * @param {Array|Object} collection The collection to iterate over.
2874      * @param {Function} iteratee The function invoked per iteration.
2875      * @returns {Array|Object} Returns `collection`.
2876      */
2877     var baseEachRight = createBaseEach(baseForOwnRight, true);
2878
2879     /**
2880      * The base implementation of `_.every` without support for iteratee shorthands.
2881      *
2882      * @private
2883      * @param {Array|Object} collection The collection to iterate over.
2884      * @param {Function} predicate The function invoked per iteration.
2885      * @returns {boolean} Returns `true` if all elements pass the predicate check,
2886      *  else `false`
2887      */
2888     function baseEvery(collection, predicate) {
2889       var result = true;
2890       baseEach(collection, function(value, index, collection) {
2891         result = !!predicate(value, index, collection);
2892         return result;
2893       });
2894       return result;
2895     }
2896
2897     /**
2898      * The base implementation of methods like `_.max` and `_.min` which accepts a
2899      * `comparator` to determine the extremum value.
2900      *
2901      * @private
2902      * @param {Array} array The array to iterate over.
2903      * @param {Function} iteratee The iteratee invoked per iteration.
2904      * @param {Function} comparator The comparator used to compare values.
2905      * @returns {*} Returns the extremum value.
2906      */
2907     function baseExtremum(array, iteratee, comparator) {
2908       var index = -1,
2909           length = array.length;
2910
2911       while (++index < length) {
2912         var value = array[index],
2913             current = iteratee(value);
2914
2915         if (current != null && (computed === undefined
2916               ? (current === current && !isSymbol(current))
2917               : comparator(current, computed)
2918             )) {
2919           var computed = current,
2920               result = value;
2921         }
2922       }
2923       return result;
2924     }
2925
2926     /**
2927      * The base implementation of `_.fill` without an iteratee call guard.
2928      *
2929      * @private
2930      * @param {Array} array The array to fill.
2931      * @param {*} value The value to fill `array` with.
2932      * @param {number} [start=0] The start position.
2933      * @param {number} [end=array.length] The end position.
2934      * @returns {Array} Returns `array`.
2935      */
2936     function baseFill(array, value, start, end) {
2937       var length = array.length;
2938
2939       start = toInteger(start);
2940       if (start < 0) {
2941         start = -start > length ? 0 : (length + start);
2942       }
2943       end = (end === undefined || end > length) ? length : toInteger(end);
2944       if (end < 0) {
2945         end += length;
2946       }
2947       end = start > end ? 0 : toLength(end);
2948       while (start < end) {
2949         array[start++] = value;
2950       }
2951       return array;
2952     }
2953
2954     /**
2955      * The base implementation of `_.filter` without support for iteratee shorthands.
2956      *
2957      * @private
2958      * @param {Array|Object} collection The collection to iterate over.
2959      * @param {Function} predicate The function invoked per iteration.
2960      * @returns {Array} Returns the new filtered array.
2961      */
2962     function baseFilter(collection, predicate) {
2963       var result = [];
2964       baseEach(collection, function(value, index, collection) {
2965         if (predicate(value, index, collection)) {
2966           result.push(value);
2967         }
2968       });
2969       return result;
2970     }
2971
2972     /**
2973      * The base implementation of `_.flatten` with support for restricting flattening.
2974      *
2975      * @private
2976      * @param {Array} array The array to flatten.
2977      * @param {number} depth The maximum recursion depth.
2978      * @param {boolean} [predicate=isFlattenable] The function invoked per iteration.
2979      * @param {boolean} [isStrict] Restrict to values that pass `predicate` checks.
2980      * @param {Array} [result=[]] The initial result value.
2981      * @returns {Array} Returns the new flattened array.
2982      */
2983     function baseFlatten(array, depth, predicate, isStrict, result) {
2984       var index = -1,
2985           length = array.length;
2986
2987       predicate || (predicate = isFlattenable);
2988       result || (result = []);
2989
2990       while (++index < length) {
2991         var value = array[index];
2992         if (depth > 0 && predicate(value)) {
2993           if (depth > 1) {
2994             // Recursively flatten arrays (susceptible to call stack limits).
2995             baseFlatten(value, depth - 1, predicate, isStrict, result);
2996           } else {
2997             arrayPush(result, value);
2998           }
2999         } else if (!isStrict) {
3000           result[result.length] = value;
3001         }
3002       }
3003       return result;
3004     }
3005
3006     /**
3007      * The base implementation of `baseForOwn` which iterates over `object`
3008      * properties returned by `keysFunc` and invokes `iteratee` for each property.
3009      * Iteratee functions may exit iteration early by explicitly returning `false`.
3010      *
3011      * @private
3012      * @param {Object} object The object to iterate over.
3013      * @param {Function} iteratee The function invoked per iteration.
3014      * @param {Function} keysFunc The function to get the keys of `object`.
3015      * @returns {Object} Returns `object`.
3016      */
3017     var baseFor = createBaseFor();
3018
3019     /**
3020      * This function is like `baseFor` except that it iterates over properties
3021      * in the opposite order.
3022      *
3023      * @private
3024      * @param {Object} object The object to iterate over.
3025      * @param {Function} iteratee The function invoked per iteration.
3026      * @param {Function} keysFunc The function to get the keys of `object`.
3027      * @returns {Object} Returns `object`.
3028      */
3029     var baseForRight = createBaseFor(true);
3030
3031     /**
3032      * The base implementation of `_.forOwn` without support for iteratee shorthands.
3033      *
3034      * @private
3035      * @param {Object} object The object to iterate over.
3036      * @param {Function} iteratee The function invoked per iteration.
3037      * @returns {Object} Returns `object`.
3038      */
3039     function baseForOwn(object, iteratee) {
3040       return object && baseFor(object, iteratee, keys);
3041     }
3042
3043     /**
3044      * The base implementation of `_.forOwnRight` without support for iteratee shorthands.
3045      *
3046      * @private
3047      * @param {Object} object The object to iterate over.
3048      * @param {Function} iteratee The function invoked per iteration.
3049      * @returns {Object} Returns `object`.
3050      */
3051     function baseForOwnRight(object, iteratee) {
3052       return object && baseForRight(object, iteratee, keys);
3053     }
3054
3055     /**
3056      * The base implementation of `_.functions` which creates an array of
3057      * `object` function property names filtered from `props`.
3058      *
3059      * @private
3060      * @param {Object} object The object to inspect.
3061      * @param {Array} props The property names to filter.
3062      * @returns {Array} Returns the function names.
3063      */
3064     function baseFunctions(object, props) {
3065       return arrayFilter(props, function(key) {
3066         return isFunction(object[key]);
3067       });
3068     }
3069
3070     /**
3071      * The base implementation of `_.get` without support for default values.
3072      *
3073      * @private
3074      * @param {Object} object The object to query.
3075      * @param {Array|string} path The path of the property to get.
3076      * @returns {*} Returns the resolved value.
3077      */
3078     function baseGet(object, path) {
3079       path = isKey(path, object) ? [path] : castPath(path);
3080
3081       var index = 0,
3082           length = path.length;
3083
3084       while (object != null && index < length) {
3085         object = object[toKey(path[index++])];
3086       }
3087       return (index && index == length) ? object : undefined;
3088     }
3089
3090     /**
3091      * The base implementation of `getAllKeys` and `getAllKeysIn` which uses
3092      * `keysFunc` and `symbolsFunc` to get the enumerable property names and
3093      * symbols of `object`.
3094      *
3095      * @private
3096      * @param {Object} object The object to query.
3097      * @param {Function} keysFunc The function to get the keys of `object`.
3098      * @param {Function} symbolsFunc The function to get the symbols of `object`.
3099      * @returns {Array} Returns the array of property names and symbols.
3100      */
3101     function baseGetAllKeys(object, keysFunc, symbolsFunc) {
3102       var result = keysFunc(object);
3103       return isArray(object) ? result : arrayPush(result, symbolsFunc(object));
3104     }
3105
3106     /**
3107      * The base implementation of `getTag` without fallbacks for buggy environments.
3108      *
3109      * @private
3110      * @param {*} value The value to query.
3111      * @returns {string} Returns the `toStringTag`.
3112      */
3113     function baseGetTag(value) {
3114       if (value == null) {
3115         return value === undefined ? undefinedTag : nullTag;
3116       }
3117       value = Object(value);
3118       return (symToStringTag && symToStringTag in value)
3119         ? getRawTag(value)
3120         : objectToString(value);
3121     }
3122
3123     /**
3124      * The base implementation of `_.gt` which doesn't coerce arguments.
3125      *
3126      * @private
3127      * @param {*} value The value to compare.
3128      * @param {*} other The other value to compare.
3129      * @returns {boolean} Returns `true` if `value` is greater than `other`,
3130      *  else `false`.
3131      */
3132     function baseGt(value, other) {
3133       return value > other;
3134     }
3135
3136     /**
3137      * The base implementation of `_.has` without support for deep paths.
3138      *
3139      * @private
3140      * @param {Object} [object] The object to query.
3141      * @param {Array|string} key The key to check.
3142      * @returns {boolean} Returns `true` if `key` exists, else `false`.
3143      */
3144     function baseHas(object, key) {
3145       return object != null && hasOwnProperty.call(object, key);
3146     }
3147
3148     /**
3149      * The base implementation of `_.hasIn` without support for deep paths.
3150      *
3151      * @private
3152      * @param {Object} [object] The object to query.
3153      * @param {Array|string} key The key to check.
3154      * @returns {boolean} Returns `true` if `key` exists, else `false`.
3155      */
3156     function baseHasIn(object, key) {
3157       return object != null && key in Object(object);
3158     }
3159
3160     /**
3161      * The base implementation of `_.inRange` which doesn't coerce arguments.
3162      *
3163      * @private
3164      * @param {number} number The number to check.
3165      * @param {number} start The start of the range.
3166      * @param {number} end The end of the range.
3167      * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
3168      */
3169     function baseInRange(number, start, end) {
3170       return number >= nativeMin(start, end) && number < nativeMax(start, end);
3171     }
3172
3173     /**
3174      * The base implementation of methods like `_.intersection`, without support
3175      * for iteratee shorthands, that accepts an array of arrays to inspect.
3176      *
3177      * @private
3178      * @param {Array} arrays The arrays to inspect.
3179      * @param {Function} [iteratee] The iteratee invoked per element.
3180      * @param {Function} [comparator] The comparator invoked per element.
3181      * @returns {Array} Returns the new array of shared values.
3182      */
3183     function baseIntersection(arrays, iteratee, comparator) {
3184       var includes = comparator ? arrayIncludesWith : arrayIncludes,
3185           length = arrays[0].length,
3186           othLength = arrays.length,
3187           othIndex = othLength,
3188           caches = Array(othLength),
3189           maxLength = Infinity,
3190           result = [];
3191
3192       while (othIndex--) {
3193         var array = arrays[othIndex];
3194         if (othIndex && iteratee) {
3195           array = arrayMap(array, baseUnary(iteratee));
3196         }
3197         maxLength = nativeMin(array.length, maxLength);
3198         caches[othIndex] = !comparator && (iteratee || (length >= 120 && array.length >= 120))
3199           ? new SetCache(othIndex && array)
3200           : undefined;
3201       }
3202       array = arrays[0];
3203
3204       var index = -1,
3205           seen = caches[0];
3206
3207       outer:
3208       while (++index < length && result.length < maxLength) {
3209         var value = array[index],
3210             computed = iteratee ? iteratee(value) : value;
3211
3212         value = (comparator || value !== 0) ? value : 0;
3213         if (!(seen
3214               ? cacheHas(seen, computed)
3215               : includes(result, computed, comparator)
3216             )) {
3217           othIndex = othLength;
3218           while (--othIndex) {
3219             var cache = caches[othIndex];
3220             if (!(cache
3221                   ? cacheHas(cache, computed)
3222                   : includes(arrays[othIndex], computed, comparator))
3223                 ) {
3224               continue outer;
3225             }
3226           }
3227           if (seen) {
3228             seen.push(computed);
3229           }
3230           result.push(value);
3231         }
3232       }
3233       return result;
3234     }
3235
3236     /**
3237      * The base implementation of `_.invert` and `_.invertBy` which inverts
3238      * `object` with values transformed by `iteratee` and set by `setter`.
3239      *
3240      * @private
3241      * @param {Object} object The object to iterate over.
3242      * @param {Function} setter The function to set `accumulator` values.
3243      * @param {Function} iteratee The iteratee to transform values.
3244      * @param {Object} accumulator The initial inverted object.
3245      * @returns {Function} Returns `accumulator`.
3246      */
3247     function baseInverter(object, setter, iteratee, accumulator) {
3248       baseForOwn(object, function(value, key, object) {
3249         setter(accumulator, iteratee(value), key, object);
3250       });
3251       return accumulator;
3252     }
3253
3254     /**
3255      * The base implementation of `_.invoke` without support for individual
3256      * method arguments.
3257      *
3258      * @private
3259      * @param {Object} object The object to query.
3260      * @param {Array|string} path The path of the method to invoke.
3261      * @param {Array} args The arguments to invoke the method with.
3262      * @returns {*} Returns the result of the invoked method.
3263      */
3264     function baseInvoke(object, path, args) {
3265       if (!isKey(path, object)) {
3266         path = castPath(path);
3267         object = parent(object, path);
3268         path = last(path);
3269       }
3270       var func = object == null ? object : object[toKey(path)];
3271       return func == null ? undefined : apply(func, object, args);
3272     }
3273
3274     /**
3275      * The base implementation of `_.isArguments`.
3276      *
3277      * @private
3278      * @param {*} value The value to check.
3279      * @returns {boolean} Returns `true` if `value` is an `arguments` object,
3280      */
3281     function baseIsArguments(value) {
3282       return isObjectLike(value) && baseGetTag(value) == argsTag;
3283     }
3284
3285     /**
3286      * The base implementation of `_.isArrayBuffer` without Node.js optimizations.
3287      *
3288      * @private
3289      * @param {*} value The value to check.
3290      * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
3291      */
3292     function baseIsArrayBuffer(value) {
3293       return isObjectLike(value) && baseGetTag(value) == arrayBufferTag;
3294     }
3295
3296     /**
3297      * The base implementation of `_.isDate` without Node.js optimizations.
3298      *
3299      * @private
3300      * @param {*} value The value to check.
3301      * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
3302      */
3303     function baseIsDate(value) {
3304       return isObjectLike(value) && baseGetTag(value) == dateTag;
3305     }
3306
3307     /**
3308      * The base implementation of `_.isEqual` which supports partial comparisons
3309      * and tracks traversed objects.
3310      *
3311      * @private
3312      * @param {*} value The value to compare.
3313      * @param {*} other The other value to compare.
3314      * @param {boolean} bitmask The bitmask flags.
3315      *  1 - Unordered comparison
3316      *  2 - Partial comparison
3317      * @param {Function} [customizer] The function to customize comparisons.
3318      * @param {Object} [stack] Tracks traversed `value` and `other` objects.
3319      * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
3320      */
3321     function baseIsEqual(value, other, bitmask, customizer, stack) {
3322       if (value === other) {
3323         return true;
3324       }
3325       if (value == null || other == null || (!isObject(value) && !isObjectLike(other))) {
3326         return value !== value && other !== other;
3327       }
3328       return baseIsEqualDeep(value, other, bitmask, customizer, baseIsEqual, stack);
3329     }
3330
3331     /**
3332      * A specialized version of `baseIsEqual` for arrays and objects which performs
3333      * deep comparisons and tracks traversed objects enabling objects with circular
3334      * references to be compared.
3335      *
3336      * @private
3337      * @param {Object} object The object to compare.
3338      * @param {Object} other The other object to compare.
3339      * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
3340      * @param {Function} customizer The function to customize comparisons.
3341      * @param {Function} equalFunc The function to determine equivalents of values.
3342      * @param {Object} [stack] Tracks traversed `object` and `other` objects.
3343      * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
3344      */
3345     function baseIsEqualDeep(object, other, bitmask, customizer, equalFunc, stack) {
3346       var objIsArr = isArray(object),
3347           othIsArr = isArray(other),
3348           objTag = arrayTag,
3349           othTag = arrayTag;
3350
3351       if (!objIsArr) {
3352         objTag = getTag(object);
3353         objTag = objTag == argsTag ? objectTag : objTag;
3354       }
3355       if (!othIsArr) {
3356         othTag = getTag(other);
3357         othTag = othTag == argsTag ? objectTag : othTag;
3358       }
3359       var objIsObj = objTag == objectTag,
3360           othIsObj = othTag == objectTag,
3361           isSameTag = objTag == othTag;
3362
3363       if (isSameTag && isBuffer(object)) {
3364         if (!isBuffer(other)) {
3365           return false;
3366         }
3367         objIsArr = true;
3368         objIsObj = false;
3369       }
3370       if (isSameTag && !objIsObj) {
3371         stack || (stack = new Stack);
3372         return (objIsArr || isTypedArray(object))
3373           ? equalArrays(object, other, bitmask, customizer, equalFunc, stack)
3374           : equalByTag(object, other, objTag, bitmask, customizer, equalFunc, stack);
3375       }
3376       if (!(bitmask & COMPARE_PARTIAL_FLAG)) {
3377         var objIsWrapped = objIsObj && hasOwnProperty.call(object, '__wrapped__'),
3378             othIsWrapped = othIsObj && hasOwnProperty.call(other, '__wrapped__');
3379
3380         if (objIsWrapped || othIsWrapped) {
3381           var objUnwrapped = objIsWrapped ? object.value() : object,
3382               othUnwrapped = othIsWrapped ? other.value() : other;
3383
3384           stack || (stack = new Stack);
3385           return equalFunc(objUnwrapped, othUnwrapped, bitmask, customizer, stack);
3386         }
3387       }
3388       if (!isSameTag) {
3389         return false;
3390       }
3391       stack || (stack = new Stack);
3392       return equalObjects(object, other, bitmask, customizer, equalFunc, stack);
3393     }
3394
3395     /**
3396      * The base implementation of `_.isMap` without Node.js optimizations.
3397      *
3398      * @private
3399      * @param {*} value The value to check.
3400      * @returns {boolean} Returns `true` if `value` is a map, else `false`.
3401      */
3402     function baseIsMap(value) {
3403       return isObjectLike(value) && getTag(value) == mapTag;
3404     }
3405
3406     /**
3407      * The base implementation of `_.isMatch` without support for iteratee shorthands.
3408      *
3409      * @private
3410      * @param {Object} object The object to inspect.
3411      * @param {Object} source The object of property values to match.
3412      * @param {Array} matchData The property names, values, and compare flags to match.
3413      * @param {Function} [customizer] The function to customize comparisons.
3414      * @returns {boolean} Returns `true` if `object` is a match, else `false`.
3415      */
3416     function baseIsMatch(object, source, matchData, customizer) {
3417       var index = matchData.length,
3418           length = index,
3419           noCustomizer = !customizer;
3420
3421       if (object == null) {
3422         return !length;
3423       }
3424       object = Object(object);
3425       while (index--) {
3426         var data = matchData[index];
3427         if ((noCustomizer && data[2])
3428               ? data[1] !== object[data[0]]
3429               : !(data[0] in object)
3430             ) {
3431           return false;
3432         }
3433       }
3434       while (++index < length) {
3435         data = matchData[index];
3436         var key = data[0],
3437             objValue = object[key],
3438             srcValue = data[1];
3439
3440         if (noCustomizer && data[2]) {
3441           if (objValue === undefined && !(key in object)) {
3442             return false;
3443           }
3444         } else {
3445           var stack = new Stack;
3446           if (customizer) {
3447             var result = customizer(objValue, srcValue, key, object, source, stack);
3448           }
3449           if (!(result === undefined
3450                 ? baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG, customizer, stack)
3451                 : result
3452               )) {
3453             return false;
3454           }
3455         }
3456       }
3457       return true;
3458     }
3459
3460     /**
3461      * The base implementation of `_.isNative` without bad shim checks.
3462      *
3463      * @private
3464      * @param {*} value The value to check.
3465      * @returns {boolean} Returns `true` if `value` is a native function,
3466      *  else `false`.
3467      */
3468     function baseIsNative(value) {
3469       if (!isObject(value) || isMasked(value)) {
3470         return false;
3471       }
3472       var pattern = isFunction(value) ? reIsNative : reIsHostCtor;
3473       return pattern.test(toSource(value));
3474     }
3475
3476     /**
3477      * The base implementation of `_.isRegExp` without Node.js optimizations.
3478      *
3479      * @private
3480      * @param {*} value The value to check.
3481      * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
3482      */
3483     function baseIsRegExp(value) {
3484       return isObjectLike(value) && baseGetTag(value) == regexpTag;
3485     }
3486
3487     /**
3488      * The base implementation of `_.isSet` without Node.js optimizations.
3489      *
3490      * @private
3491      * @param {*} value The value to check.
3492      * @returns {boolean} Returns `true` if `value` is a set, else `false`.
3493      */
3494     function baseIsSet(value) {
3495       return isObjectLike(value) && getTag(value) == setTag;
3496     }
3497
3498     /**
3499      * The base implementation of `_.isTypedArray` without Node.js optimizations.
3500      *
3501      * @private
3502      * @param {*} value The value to check.
3503      * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
3504      */
3505     function baseIsTypedArray(value) {
3506       return isObjectLike(value) &&
3507         isLength(value.length) && !!typedArrayTags[baseGetTag(value)];
3508     }
3509
3510     /**
3511      * The base implementation of `_.iteratee`.
3512      *
3513      * @private
3514      * @param {*} [value=_.identity] The value to convert to an iteratee.
3515      * @returns {Function} Returns the iteratee.
3516      */
3517     function baseIteratee(value) {
3518       // Don't store the `typeof` result in a variable to avoid a JIT bug in Safari 9.
3519       // See https://bugs.webkit.org/show_bug.cgi?id=156034 for more details.
3520       if (typeof value == 'function') {
3521         return value;
3522       }
3523       if (value == null) {
3524         return identity;
3525       }
3526       if (typeof value == 'object') {
3527         return isArray(value)
3528           ? baseMatchesProperty(value[0], value[1])
3529           : baseMatches(value);
3530       }
3531       return property(value);
3532     }
3533
3534     /**
3535      * The base implementation of `_.keys` which doesn't treat sparse arrays as dense.
3536      *
3537      * @private
3538      * @param {Object} object The object to query.
3539      * @returns {Array} Returns the array of property names.
3540      */
3541     function baseKeys(object) {
3542       if (!isPrototype(object)) {
3543         return nativeKeys(object);
3544       }
3545       var result = [];
3546       for (var key in Object(object)) {
3547         if (hasOwnProperty.call(object, key) && key != 'constructor') {
3548           result.push(key);
3549         }
3550       }
3551       return result;
3552     }
3553
3554     /**
3555      * The base implementation of `_.keysIn` which doesn't treat sparse arrays as dense.
3556      *
3557      * @private
3558      * @param {Object} object The object to query.
3559      * @returns {Array} Returns the array of property names.
3560      */
3561     function baseKeysIn(object) {
3562       if (!isObject(object)) {
3563         return nativeKeysIn(object);
3564       }
3565       var isProto = isPrototype(object),
3566           result = [];
3567
3568       for (var key in object) {
3569         if (!(key == 'constructor' && (isProto || !hasOwnProperty.call(object, key)))) {
3570           result.push(key);
3571         }
3572       }
3573       return result;
3574     }
3575
3576     /**
3577      * The base implementation of `_.lt` which doesn't coerce arguments.
3578      *
3579      * @private
3580      * @param {*} value The value to compare.
3581      * @param {*} other The other value to compare.
3582      * @returns {boolean} Returns `true` if `value` is less than `other`,
3583      *  else `false`.
3584      */
3585     function baseLt(value, other) {
3586       return value < other;
3587     }
3588
3589     /**
3590      * The base implementation of `_.map` without support for iteratee shorthands.
3591      *
3592      * @private
3593      * @param {Array|Object} collection The collection to iterate over.
3594      * @param {Function} iteratee The function invoked per iteration.
3595      * @returns {Array} Returns the new mapped array.
3596      */
3597     function baseMap(collection, iteratee) {
3598       var index = -1,
3599           result = isArrayLike(collection) ? Array(collection.length) : [];
3600
3601       baseEach(collection, function(value, key, collection) {
3602         result[++index] = iteratee(value, key, collection);
3603       });
3604       return result;
3605     }
3606
3607     /**
3608      * The base implementation of `_.matches` which doesn't clone `source`.
3609      *
3610      * @private
3611      * @param {Object} source The object of property values to match.
3612      * @returns {Function} Returns the new spec function.
3613      */
3614     function baseMatches(source) {
3615       var matchData = getMatchData(source);
3616       if (matchData.length == 1 && matchData[0][2]) {
3617         return matchesStrictComparable(matchData[0][0], matchData[0][1]);
3618       }
3619       return function(object) {
3620         return object === source || baseIsMatch(object, source, matchData);
3621       };
3622     }
3623
3624     /**
3625      * The base implementation of `_.matchesProperty` which doesn't clone `srcValue`.
3626      *
3627      * @private
3628      * @param {string} path The path of the property to get.
3629      * @param {*} srcValue The value to match.
3630      * @returns {Function} Returns the new spec function.
3631      */
3632     function baseMatchesProperty(path, srcValue) {
3633       if (isKey(path) && isStrictComparable(srcValue)) {
3634         return matchesStrictComparable(toKey(path), srcValue);
3635       }
3636       return function(object) {
3637         var objValue = get(object, path);
3638         return (objValue === undefined && objValue === srcValue)
3639           ? hasIn(object, path)
3640           : baseIsEqual(srcValue, objValue, COMPARE_PARTIAL_FLAG | COMPARE_UNORDERED_FLAG);
3641       };
3642     }
3643
3644     /**
3645      * The base implementation of `_.merge` without support for multiple sources.
3646      *
3647      * @private
3648      * @param {Object} object The destination object.
3649      * @param {Object} source The source object.
3650      * @param {number} srcIndex The index of `source`.
3651      * @param {Function} [customizer] The function to customize merged values.
3652      * @param {Object} [stack] Tracks traversed source values and their merged
3653      *  counterparts.
3654      */
3655     function baseMerge(object, source, srcIndex, customizer, stack) {
3656       if (object === source) {
3657         return;
3658       }
3659       baseFor(source, function(srcValue, key) {
3660         if (isObject(srcValue)) {
3661           stack || (stack = new Stack);
3662           baseMergeDeep(object, source, key, srcIndex, baseMerge, customizer, stack);
3663         }
3664         else {
3665           var newValue = customizer
3666             ? customizer(object[key], srcValue, (key + ''), object, source, stack)
3667             : undefined;
3668
3669           if (newValue === undefined) {
3670             newValue = srcValue;
3671           }
3672           assignMergeValue(object, key, newValue);
3673         }
3674       }, keysIn);
3675     }
3676
3677     /**
3678      * A specialized version of `baseMerge` for arrays and objects which performs
3679      * deep merges and tracks traversed objects enabling objects with circular
3680      * references to be merged.
3681      *
3682      * @private
3683      * @param {Object} object The destination object.
3684      * @param {Object} source The source object.
3685      * @param {string} key The key of the value to merge.
3686      * @param {number} srcIndex The index of `source`.
3687      * @param {Function} mergeFunc The function to merge values.
3688      * @param {Function} [customizer] The function to customize assigned values.
3689      * @param {Object} [stack] Tracks traversed source values and their merged
3690      *  counterparts.
3691      */
3692     function baseMergeDeep(object, source, key, srcIndex, mergeFunc, customizer, stack) {
3693       var objValue = object[key],
3694           srcValue = source[key],
3695           stacked = stack.get(srcValue);
3696
3697       if (stacked) {
3698         assignMergeValue(object, key, stacked);
3699         return;
3700       }
3701       var newValue = customizer
3702         ? customizer(objValue, srcValue, (key + ''), object, source, stack)
3703         : undefined;
3704
3705       var isCommon = newValue === undefined;
3706
3707       if (isCommon) {
3708         var isArr = isArray(srcValue),
3709             isBuff = !isArr && isBuffer(srcValue),
3710             isTyped = !isArr && !isBuff && isTypedArray(srcValue);
3711
3712         newValue = srcValue;
3713         if (isArr || isBuff || isTyped) {
3714           if (isArray(objValue)) {
3715             newValue = objValue;
3716           }
3717           else if (isArrayLikeObject(objValue)) {
3718             newValue = copyArray(objValue);
3719           }
3720           else if (isBuff) {
3721             isCommon = false;
3722             newValue = cloneBuffer(srcValue, true);
3723           }
3724           else if (isTyped) {
3725             isCommon = false;
3726             newValue = cloneTypedArray(srcValue, true);
3727           }
3728           else {
3729             newValue = [];
3730           }
3731         }
3732         else if (isPlainObject(srcValue) || isArguments(srcValue)) {
3733           newValue = objValue;
3734           if (isArguments(objValue)) {
3735             newValue = toPlainObject(objValue);
3736           }
3737           else if (!isObject(objValue) || (srcIndex && isFunction(objValue))) {
3738             newValue = initCloneObject(srcValue);
3739           }
3740         }
3741         else {
3742           isCommon = false;
3743         }
3744       }
3745       if (isCommon) {
3746         // Recursively merge objects and arrays (susceptible to call stack limits).
3747         stack.set(srcValue, newValue);
3748         mergeFunc(newValue, srcValue, srcIndex, customizer, stack);
3749         stack['delete'](srcValue);
3750       }
3751       assignMergeValue(object, key, newValue);
3752     }
3753
3754     /**
3755      * The base implementation of `_.nth` which doesn't coerce arguments.
3756      *
3757      * @private
3758      * @param {Array} array The array to query.
3759      * @param {number} n The index of the element to return.
3760      * @returns {*} Returns the nth element of `array`.
3761      */
3762     function baseNth(array, n) {
3763       var length = array.length;
3764       if (!length) {
3765         return;
3766       }
3767       n += n < 0 ? length : 0;
3768       return isIndex(n, length) ? array[n] : undefined;
3769     }
3770
3771     /**
3772      * The base implementation of `_.orderBy` without param guards.
3773      *
3774      * @private
3775      * @param {Array|Object} collection The collection to iterate over.
3776      * @param {Function[]|Object[]|string[]} iteratees The iteratees to sort by.
3777      * @param {string[]} orders The sort orders of `iteratees`.
3778      * @returns {Array} Returns the new sorted array.
3779      */
3780     function baseOrderBy(collection, iteratees, orders) {
3781       var index = -1;
3782       iteratees = arrayMap(iteratees.length ? iteratees : [identity], baseUnary(getIteratee()));
3783
3784       var result = baseMap(collection, function(value, key, collection) {
3785         var criteria = arrayMap(iteratees, function(iteratee) {
3786           return iteratee(value);
3787         });
3788         return { 'criteria': criteria, 'index': ++index, 'value': value };
3789       });
3790
3791       return baseSortBy(result, function(object, other) {
3792         return compareMultiple(object, other, orders);
3793       });
3794     }
3795
3796     /**
3797      * The base implementation of `_.pick` without support for individual
3798      * property identifiers.
3799      *
3800      * @private
3801      * @param {Object} object The source object.
3802      * @param {string[]} paths The property paths to pick.
3803      * @returns {Object} Returns the new object.
3804      */
3805     function basePick(object, paths) {
3806       object = Object(object);
3807       return basePickBy(object, paths, function(value, path) {
3808         return hasIn(object, path);
3809       });
3810     }
3811
3812     /**
3813      * The base implementation of  `_.pickBy` without support for iteratee shorthands.
3814      *
3815      * @private
3816      * @param {Object} object The source object.
3817      * @param {string[]} paths The property paths to pick.
3818      * @param {Function} predicate The function invoked per property.
3819      * @returns {Object} Returns the new object.
3820      */
3821     function basePickBy(object, paths, predicate) {
3822       var index = -1,
3823           length = paths.length,
3824           result = {};
3825
3826       while (++index < length) {
3827         var path = paths[index],
3828             value = baseGet(object, path);
3829
3830         if (predicate(value, path)) {
3831           baseSet(result, path, value);
3832         }
3833       }
3834       return result;
3835     }
3836
3837     /**
3838      * A specialized version of `baseProperty` which supports deep paths.
3839      *
3840      * @private
3841      * @param {Array|string} path The path of the property to get.
3842      * @returns {Function} Returns the new accessor function.
3843      */
3844     function basePropertyDeep(path) {
3845       return function(object) {
3846         return baseGet(object, path);
3847       };
3848     }
3849
3850     /**
3851      * The base implementation of `_.pullAllBy` without support for iteratee
3852      * shorthands.
3853      *
3854      * @private
3855      * @param {Array} array The array to modify.
3856      * @param {Array} values The values to remove.
3857      * @param {Function} [iteratee] The iteratee invoked per element.
3858      * @param {Function} [comparator] The comparator invoked per element.
3859      * @returns {Array} Returns `array`.
3860      */
3861     function basePullAll(array, values, iteratee, comparator) {
3862       var indexOf = comparator ? baseIndexOfWith : baseIndexOf,
3863           index = -1,
3864           length = values.length,
3865           seen = array;
3866
3867       if (array === values) {
3868         values = copyArray(values);
3869       }
3870       if (iteratee) {
3871         seen = arrayMap(array, baseUnary(iteratee));
3872       }
3873       while (++index < length) {
3874         var fromIndex = 0,
3875             value = values[index],
3876             computed = iteratee ? iteratee(value) : value;
3877
3878         while ((fromIndex = indexOf(seen, computed, fromIndex, comparator)) > -1) {
3879           if (seen !== array) {
3880             splice.call(seen, fromIndex, 1);
3881           }
3882           splice.call(array, fromIndex, 1);
3883         }
3884       }
3885       return array;
3886     }
3887
3888     /**
3889      * The base implementation of `_.pullAt` without support for individual
3890      * indexes or capturing the removed elements.
3891      *
3892      * @private
3893      * @param {Array} array The array to modify.
3894      * @param {number[]} indexes The indexes of elements to remove.
3895      * @returns {Array} Returns `array`.
3896      */
3897     function basePullAt(array, indexes) {
3898       var length = array ? indexes.length : 0,
3899           lastIndex = length - 1;
3900
3901       while (length--) {
3902         var index = indexes[length];
3903         if (length == lastIndex || index !== previous) {
3904           var previous = index;
3905           if (isIndex(index)) {
3906             splice.call(array, index, 1);
3907           }
3908           else if (!isKey(index, array)) {
3909             var path = castPath(index),
3910                 object = parent(array, path);
3911
3912             if (object != null) {
3913               delete object[toKey(last(path))];
3914             }
3915           }
3916           else {
3917             delete array[toKey(index)];
3918           }
3919         }
3920       }
3921       return array;
3922     }
3923
3924     /**
3925      * The base implementation of `_.random` without support for returning
3926      * floating-point numbers.
3927      *
3928      * @private
3929      * @param {number} lower The lower bound.
3930      * @param {number} upper The upper bound.
3931      * @returns {number} Returns the random number.
3932      */
3933     function baseRandom(lower, upper) {
3934       return lower + nativeFloor(nativeRandom() * (upper - lower + 1));
3935     }
3936
3937     /**
3938      * The base implementation of `_.range` and `_.rangeRight` which doesn't
3939      * coerce arguments.
3940      *
3941      * @private
3942      * @param {number} start The start of the range.
3943      * @param {number} end The end of the range.
3944      * @param {number} step The value to increment or decrement by.
3945      * @param {boolean} [fromRight] Specify iterating from right to left.
3946      * @returns {Array} Returns the range of numbers.
3947      */
3948     function baseRange(start, end, step, fromRight) {
3949       var index = -1,
3950           length = nativeMax(nativeCeil((end - start) / (step || 1)), 0),
3951           result = Array(length);
3952
3953       while (length--) {
3954         result[fromRight ? length : ++index] = start;
3955         start += step;
3956       }
3957       return result;
3958     }
3959
3960     /**
3961      * The base implementation of `_.repeat` which doesn't coerce arguments.
3962      *
3963      * @private
3964      * @param {string} string The string to repeat.
3965      * @param {number} n The number of times to repeat the string.
3966      * @returns {string} Returns the repeated string.
3967      */
3968     function baseRepeat(string, n) {
3969       var result = '';
3970       if (!string || n < 1 || n > MAX_SAFE_INTEGER) {
3971         return result;
3972       }
3973       // Leverage the exponentiation by squaring algorithm for a faster repeat.
3974       // See https://en.wikipedia.org/wiki/Exponentiation_by_squaring for more details.
3975       do {
3976         if (n % 2) {
3977           result += string;
3978         }
3979         n = nativeFloor(n / 2);
3980         if (n) {
3981           string += string;
3982         }
3983       } while (n);
3984
3985       return result;
3986     }
3987
3988     /**
3989      * The base implementation of `_.rest` which doesn't validate or coerce arguments.
3990      *
3991      * @private
3992      * @param {Function} func The function to apply a rest parameter to.
3993      * @param {number} [start=func.length-1] The start position of the rest parameter.
3994      * @returns {Function} Returns the new function.
3995      */
3996     function baseRest(func, start) {
3997       return setToString(overRest(func, start, identity), func + '');
3998     }
3999
4000     /**
4001      * The base implementation of `_.sample`.
4002      *
4003      * @private
4004      * @param {Array|Object} collection The collection to sample.
4005      * @returns {*} Returns the random element.
4006      */
4007     function baseSample(collection) {
4008       return arraySample(values(collection));
4009     }
4010
4011     /**
4012      * The base implementation of `_.sampleSize` without param guards.
4013      *
4014      * @private
4015      * @param {Array|Object} collection The collection to sample.
4016      * @param {number} n The number of elements to sample.
4017      * @returns {Array} Returns the random elements.
4018      */
4019     function baseSampleSize(collection, n) {
4020       var array = values(collection);
4021       return shuffleSelf(array, baseClamp(n, 0, array.length));
4022     }
4023
4024     /**
4025      * The base implementation of `_.set`.
4026      *
4027      * @private
4028      * @param {Object} object The object to modify.
4029      * @param {Array|string} path The path of the property to set.
4030      * @param {*} value The value to set.
4031      * @param {Function} [customizer] The function to customize path creation.
4032      * @returns {Object} Returns `object`.
4033      */
4034     function baseSet(object, path, value, customizer) {
4035       if (!isObject(object)) {
4036         return object;
4037       }
4038       path = isKey(path, object) ? [path] : castPath(path);
4039
4040       var index = -1,
4041           length = path.length,
4042           lastIndex = length - 1,
4043           nested = object;
4044
4045       while (nested != null && ++index < length) {
4046         var key = toKey(path[index]),
4047             newValue = value;
4048
4049         if (index != lastIndex) {
4050           var objValue = nested[key];
4051           newValue = customizer ? customizer(objValue, key, nested) : undefined;
4052           if (newValue === undefined) {
4053             newValue = isObject(objValue)
4054               ? objValue
4055               : (isIndex(path[index + 1]) ? [] : {});
4056           }
4057         }
4058         assignValue(nested, key, newValue);
4059         nested = nested[key];
4060       }
4061       return object;
4062     }
4063
4064     /**
4065      * The base implementation of `setData` without support for hot loop shorting.
4066      *
4067      * @private
4068      * @param {Function} func The function to associate metadata with.
4069      * @param {*} data The metadata.
4070      * @returns {Function} Returns `func`.
4071      */
4072     var baseSetData = !metaMap ? identity : function(func, data) {
4073       metaMap.set(func, data);
4074       return func;
4075     };
4076
4077     /**
4078      * The base implementation of `setToString` without support for hot loop shorting.
4079      *
4080      * @private
4081      * @param {Function} func The function to modify.
4082      * @param {Function} string The `toString` result.
4083      * @returns {Function} Returns `func`.
4084      */
4085     var baseSetToString = !defineProperty ? identity : function(func, string) {
4086       return defineProperty(func, 'toString', {
4087         'configurable': true,
4088         'enumerable': false,
4089         'value': constant(string),
4090         'writable': true
4091       });
4092     };
4093
4094     /**
4095      * The base implementation of `_.shuffle`.
4096      *
4097      * @private
4098      * @param {Array|Object} collection The collection to shuffle.
4099      * @returns {Array} Returns the new shuffled array.
4100      */
4101     function baseShuffle(collection) {
4102       return shuffleSelf(values(collection));
4103     }
4104
4105     /**
4106      * The base implementation of `_.slice` without an iteratee call guard.
4107      *
4108      * @private
4109      * @param {Array} array The array to slice.
4110      * @param {number} [start=0] The start position.
4111      * @param {number} [end=array.length] The end position.
4112      * @returns {Array} Returns the slice of `array`.
4113      */
4114     function baseSlice(array, start, end) {
4115       var index = -1,
4116           length = array.length;
4117
4118       if (start < 0) {
4119         start = -start > length ? 0 : (length + start);
4120       }
4121       end = end > length ? length : end;
4122       if (end < 0) {
4123         end += length;
4124       }
4125       length = start > end ? 0 : ((end - start) >>> 0);
4126       start >>>= 0;
4127
4128       var result = Array(length);
4129       while (++index < length) {
4130         result[index] = array[index + start];
4131       }
4132       return result;
4133     }
4134
4135     /**
4136      * The base implementation of `_.some` without support for iteratee shorthands.
4137      *
4138      * @private
4139      * @param {Array|Object} collection The collection to iterate over.
4140      * @param {Function} predicate The function invoked per iteration.
4141      * @returns {boolean} Returns `true` if any element passes the predicate check,
4142      *  else `false`.
4143      */
4144     function baseSome(collection, predicate) {
4145       var result;
4146
4147       baseEach(collection, function(value, index, collection) {
4148         result = predicate(value, index, collection);
4149         return !result;
4150       });
4151       return !!result;
4152     }
4153
4154     /**
4155      * The base implementation of `_.sortedIndex` and `_.sortedLastIndex` which
4156      * performs a binary search of `array` to determine the index at which `value`
4157      * should be inserted into `array` in order to maintain its sort order.
4158      *
4159      * @private
4160      * @param {Array} array The sorted array to inspect.
4161      * @param {*} value The value to evaluate.
4162      * @param {boolean} [retHighest] Specify returning the highest qualified index.
4163      * @returns {number} Returns the index at which `value` should be inserted
4164      *  into `array`.
4165      */
4166     function baseSortedIndex(array, value, retHighest) {
4167       var low = 0,
4168           high = array == null ? low : array.length;
4169
4170       if (typeof value == 'number' && value === value && high <= HALF_MAX_ARRAY_LENGTH) {
4171         while (low < high) {
4172           var mid = (low + high) >>> 1,
4173               computed = array[mid];
4174
4175           if (computed !== null && !isSymbol(computed) &&
4176               (retHighest ? (computed <= value) : (computed < value))) {
4177             low = mid + 1;
4178           } else {
4179             high = mid;
4180           }
4181         }
4182         return high;
4183       }
4184       return baseSortedIndexBy(array, value, identity, retHighest);
4185     }
4186
4187     /**
4188      * The base implementation of `_.sortedIndexBy` and `_.sortedLastIndexBy`
4189      * which invokes `iteratee` for `value` and each element of `array` to compute
4190      * their sort ranking. The iteratee is invoked with one argument; (value).
4191      *
4192      * @private
4193      * @param {Array} array The sorted array to inspect.
4194      * @param {*} value The value to evaluate.
4195      * @param {Function} iteratee The iteratee invoked per element.
4196      * @param {boolean} [retHighest] Specify returning the highest qualified index.
4197      * @returns {number} Returns the index at which `value` should be inserted
4198      *  into `array`.
4199      */
4200     function baseSortedIndexBy(array, value, iteratee, retHighest) {
4201       value = iteratee(value);
4202
4203       var low = 0,
4204           high = array == null ? 0 : array.length,
4205           valIsNaN = value !== value,
4206           valIsNull = value === null,
4207           valIsSymbol = isSymbol(value),
4208           valIsUndefined = value === undefined;
4209
4210       while (low < high) {
4211         var mid = nativeFloor((low + high) / 2),
4212             computed = iteratee(array[mid]),
4213             othIsDefined = computed !== undefined,
4214             othIsNull = computed === null,
4215             othIsReflexive = computed === computed,
4216             othIsSymbol = isSymbol(computed);
4217
4218         if (valIsNaN) {
4219           var setLow = retHighest || othIsReflexive;
4220         } else if (valIsUndefined) {
4221           setLow = othIsReflexive && (retHighest || othIsDefined);
4222         } else if (valIsNull) {
4223           setLow = othIsReflexive && othIsDefined && (retHighest || !othIsNull);
4224         } else if (valIsSymbol) {
4225           setLow = othIsReflexive && othIsDefined && !othIsNull && (retHighest || !othIsSymbol);
4226         } else if (othIsNull || othIsSymbol) {
4227           setLow = false;
4228         } else {
4229           setLow = retHighest ? (computed <= value) : (computed < value);
4230         }
4231         if (setLow) {
4232           low = mid + 1;
4233         } else {
4234           high = mid;
4235         }
4236       }
4237       return nativeMin(high, MAX_ARRAY_INDEX);
4238     }
4239
4240     /**
4241      * The base implementation of `_.sortedUniq` and `_.sortedUniqBy` without
4242      * support for iteratee shorthands.
4243      *
4244      * @private
4245      * @param {Array} array The array to inspect.
4246      * @param {Function} [iteratee] The iteratee invoked per element.
4247      * @returns {Array} Returns the new duplicate free array.
4248      */
4249     function baseSortedUniq(array, iteratee) {
4250       var index = -1,
4251           length = array.length,
4252           resIndex = 0,
4253           result = [];
4254
4255       while (++index < length) {
4256         var value = array[index],
4257             computed = iteratee ? iteratee(value) : value;
4258
4259         if (!index || !eq(computed, seen)) {
4260           var seen = computed;
4261           result[resIndex++] = value === 0 ? 0 : value;
4262         }
4263       }
4264       return result;
4265     }
4266
4267     /**
4268      * The base implementation of `_.toNumber` which doesn't ensure correct
4269      * conversions of binary, hexadecimal, or octal string values.
4270      *
4271      * @private
4272      * @param {*} value The value to process.
4273      * @returns {number} Returns the number.
4274      */
4275     function baseToNumber(value) {
4276       if (typeof value == 'number') {
4277         return value;
4278       }
4279       if (isSymbol(value)) {
4280         return NAN;
4281       }
4282       return +value;
4283     }
4284
4285     /**
4286      * The base implementation of `_.toString` which doesn't convert nullish
4287      * values to empty strings.
4288      *
4289      * @private
4290      * @param {*} value The value to process.
4291      * @returns {string} Returns the string.
4292      */
4293     function baseToString(value) {
4294       // Exit early for strings to avoid a performance hit in some environments.
4295       if (typeof value == 'string') {
4296         return value;
4297       }
4298       if (isArray(value)) {
4299         // Recursively convert values (susceptible to call stack limits).
4300         return arrayMap(value, baseToString) + '';
4301       }
4302       if (isSymbol(value)) {
4303         return symbolToString ? symbolToString.call(value) : '';
4304       }
4305       var result = (value + '');
4306       return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
4307     }
4308
4309     /**
4310      * The base implementation of `_.uniqBy` without support for iteratee shorthands.
4311      *
4312      * @private
4313      * @param {Array} array The array to inspect.
4314      * @param {Function} [iteratee] The iteratee invoked per element.
4315      * @param {Function} [comparator] The comparator invoked per element.
4316      * @returns {Array} Returns the new duplicate free array.
4317      */
4318     function baseUniq(array, iteratee, comparator) {
4319       var index = -1,
4320           includes = arrayIncludes,
4321           length = array.length,
4322           isCommon = true,
4323           result = [],
4324           seen = result;
4325
4326       if (comparator) {
4327         isCommon = false;
4328         includes = arrayIncludesWith;
4329       }
4330       else if (length >= LARGE_ARRAY_SIZE) {
4331         var set = iteratee ? null : createSet(array);
4332         if (set) {
4333           return setToArray(set);
4334         }
4335         isCommon = false;
4336         includes = cacheHas;
4337         seen = new SetCache;
4338       }
4339       else {
4340         seen = iteratee ? [] : result;
4341       }
4342       outer:
4343       while (++index < length) {
4344         var value = array[index],
4345             computed = iteratee ? iteratee(value) : value;
4346
4347         value = (comparator || value !== 0) ? value : 0;
4348         if (isCommon && computed === computed) {
4349           var seenIndex = seen.length;
4350           while (seenIndex--) {
4351             if (seen[seenIndex] === computed) {
4352               continue outer;
4353             }
4354           }
4355           if (iteratee) {
4356             seen.push(computed);
4357           }
4358           result.push(value);
4359         }
4360         else if (!includes(seen, computed, comparator)) {
4361           if (seen !== result) {
4362             seen.push(computed);
4363           }
4364           result.push(value);
4365         }
4366       }
4367       return result;
4368     }
4369
4370     /**
4371      * The base implementation of `_.unset`.
4372      *
4373      * @private
4374      * @param {Object} object The object to modify.
4375      * @param {Array|string} path The property path to unset.
4376      * @returns {boolean} Returns `true` if the property is deleted, else `false`.
4377      */
4378     function baseUnset(object, path) {
4379       path = isKey(path, object) ? [path] : castPath(path);
4380       object = parent(object, path);
4381
4382       var key = toKey(last(path));
4383       return !(object != null && hasOwnProperty.call(object, key)) || delete object[key];
4384     }
4385
4386     /**
4387      * The base implementation of `_.update`.
4388      *
4389      * @private
4390      * @param {Object} object The object to modify.
4391      * @param {Array|string} path The path of the property to update.
4392      * @param {Function} updater The function to produce the updated value.
4393      * @param {Function} [customizer] The function to customize path creation.
4394      * @returns {Object} Returns `object`.
4395      */
4396     function baseUpdate(object, path, updater, customizer) {
4397       return baseSet(object, path, updater(baseGet(object, path)), customizer);
4398     }
4399
4400     /**
4401      * The base implementation of methods like `_.dropWhile` and `_.takeWhile`
4402      * without support for iteratee shorthands.
4403      *
4404      * @private
4405      * @param {Array} array The array to query.
4406      * @param {Function} predicate The function invoked per iteration.
4407      * @param {boolean} [isDrop] Specify dropping elements instead of taking them.
4408      * @param {boolean} [fromRight] Specify iterating from right to left.
4409      * @returns {Array} Returns the slice of `array`.
4410      */
4411     function baseWhile(array, predicate, isDrop, fromRight) {
4412       var length = array.length,
4413           index = fromRight ? length : -1;
4414
4415       while ((fromRight ? index-- : ++index < length) &&
4416         predicate(array[index], index, array)) {}
4417
4418       return isDrop
4419         ? baseSlice(array, (fromRight ? 0 : index), (fromRight ? index + 1 : length))
4420         : baseSlice(array, (fromRight ? index + 1 : 0), (fromRight ? length : index));
4421     }
4422
4423     /**
4424      * The base implementation of `wrapperValue` which returns the result of
4425      * performing a sequence of actions on the unwrapped `value`, where each
4426      * successive action is supplied the return value of the previous.
4427      *
4428      * @private
4429      * @param {*} value The unwrapped value.
4430      * @param {Array} actions Actions to perform to resolve the unwrapped value.
4431      * @returns {*} Returns the resolved value.
4432      */
4433     function baseWrapperValue(value, actions) {
4434       var result = value;
4435       if (result instanceof LazyWrapper) {
4436         result = result.value();
4437       }
4438       return arrayReduce(actions, function(result, action) {
4439         return action.func.apply(action.thisArg, arrayPush([result], action.args));
4440       }, result);
4441     }
4442
4443     /**
4444      * The base implementation of methods like `_.xor`, without support for
4445      * iteratee shorthands, that accepts an array of arrays to inspect.
4446      *
4447      * @private
4448      * @param {Array} arrays The arrays to inspect.
4449      * @param {Function} [iteratee] The iteratee invoked per element.
4450      * @param {Function} [comparator] The comparator invoked per element.
4451      * @returns {Array} Returns the new array of values.
4452      */
4453     function baseXor(arrays, iteratee, comparator) {
4454       var length = arrays.length;
4455       if (length < 2) {
4456         return length ? baseUniq(arrays[0]) : [];
4457       }
4458       var index = -1,
4459           result = Array(length);
4460
4461       while (++index < length) {
4462         var array = arrays[index],
4463             othIndex = -1;
4464
4465         while (++othIndex < length) {
4466           if (othIndex != index) {
4467             result[index] = baseDifference(result[index] || array, arrays[othIndex], iteratee, comparator);
4468           }
4469         }
4470       }
4471       return baseUniq(baseFlatten(result, 1), iteratee, comparator);
4472     }
4473
4474     /**
4475      * This base implementation of `_.zipObject` which assigns values using `assignFunc`.
4476      *
4477      * @private
4478      * @param {Array} props The property identifiers.
4479      * @param {Array} values The property values.
4480      * @param {Function} assignFunc The function to assign values.
4481      * @returns {Object} Returns the new object.
4482      */
4483     function baseZipObject(props, values, assignFunc) {
4484       var index = -1,
4485           length = props.length,
4486           valsLength = values.length,
4487           result = {};
4488
4489       while (++index < length) {
4490         var value = index < valsLength ? values[index] : undefined;
4491         assignFunc(result, props[index], value);
4492       }
4493       return result;
4494     }
4495
4496     /**
4497      * Casts `value` to an empty array if it's not an array like object.
4498      *
4499      * @private
4500      * @param {*} value The value to inspect.
4501      * @returns {Array|Object} Returns the cast array-like object.
4502      */
4503     function castArrayLikeObject(value) {
4504       return isArrayLikeObject(value) ? value : [];
4505     }
4506
4507     /**
4508      * Casts `value` to `identity` if it's not a function.
4509      *
4510      * @private
4511      * @param {*} value The value to inspect.
4512      * @returns {Function} Returns cast function.
4513      */
4514     function castFunction(value) {
4515       return typeof value == 'function' ? value : identity;
4516     }
4517
4518     /**
4519      * Casts `value` to a path array if it's not one.
4520      *
4521      * @private
4522      * @param {*} value The value to inspect.
4523      * @returns {Array} Returns the cast property path array.
4524      */
4525     function castPath(value) {
4526       return isArray(value) ? value : stringToPath(value);
4527     }
4528
4529     /**
4530      * A `baseRest` alias which can be replaced with `identity` by module
4531      * replacement plugins.
4532      *
4533      * @private
4534      * @type {Function}
4535      * @param {Function} func The function to apply a rest parameter to.
4536      * @returns {Function} Returns the new function.
4537      */
4538     var castRest = baseRest;
4539
4540     /**
4541      * Casts `array` to a slice if it's needed.
4542      *
4543      * @private
4544      * @param {Array} array The array to inspect.
4545      * @param {number} start The start position.
4546      * @param {number} [end=array.length] The end position.
4547      * @returns {Array} Returns the cast slice.
4548      */
4549     function castSlice(array, start, end) {
4550       var length = array.length;
4551       end = end === undefined ? length : end;
4552       return (!start && end >= length) ? array : baseSlice(array, start, end);
4553     }
4554
4555     /**
4556      * A simple wrapper around the global [`clearTimeout`](https://mdn.io/clearTimeout).
4557      *
4558      * @private
4559      * @param {number|Object} id The timer id or timeout object of the timer to clear.
4560      */
4561     var clearTimeout = ctxClearTimeout || function(id) {
4562       return root.clearTimeout(id);
4563     };
4564
4565     /**
4566      * Creates a clone of  `buffer`.
4567      *
4568      * @private
4569      * @param {Buffer} buffer The buffer to clone.
4570      * @param {boolean} [isDeep] Specify a deep clone.
4571      * @returns {Buffer} Returns the cloned buffer.
4572      */
4573     function cloneBuffer(buffer, isDeep) {
4574       if (isDeep) {
4575         return buffer.slice();
4576       }
4577       var length = buffer.length,
4578           result = allocUnsafe ? allocUnsafe(length) : new buffer.constructor(length);
4579
4580       buffer.copy(result);
4581       return result;
4582     }
4583
4584     /**
4585      * Creates a clone of `arrayBuffer`.
4586      *
4587      * @private
4588      * @param {ArrayBuffer} arrayBuffer The array buffer to clone.
4589      * @returns {ArrayBuffer} Returns the cloned array buffer.
4590      */
4591     function cloneArrayBuffer(arrayBuffer) {
4592       var result = new arrayBuffer.constructor(arrayBuffer.byteLength);
4593       new Uint8Array(result).set(new Uint8Array(arrayBuffer));
4594       return result;
4595     }
4596
4597     /**
4598      * Creates a clone of `dataView`.
4599      *
4600      * @private
4601      * @param {Object} dataView The data view to clone.
4602      * @param {boolean} [isDeep] Specify a deep clone.
4603      * @returns {Object} Returns the cloned data view.
4604      */
4605     function cloneDataView(dataView, isDeep) {
4606       var buffer = isDeep ? cloneArrayBuffer(dataView.buffer) : dataView.buffer;
4607       return new dataView.constructor(buffer, dataView.byteOffset, dataView.byteLength);
4608     }
4609
4610     /**
4611      * Creates a clone of `map`.
4612      *
4613      * @private
4614      * @param {Object} map The map to clone.
4615      * @param {Function} cloneFunc The function to clone values.
4616      * @param {boolean} [isDeep] Specify a deep clone.
4617      * @returns {Object} Returns the cloned map.
4618      */
4619     function cloneMap(map, isDeep, cloneFunc) {
4620       var array = isDeep ? cloneFunc(mapToArray(map), CLONE_DEEP_FLAG) : mapToArray(map);
4621       return arrayReduce(array, addMapEntry, new map.constructor);
4622     }
4623
4624     /**
4625      * Creates a clone of `regexp`.
4626      *
4627      * @private
4628      * @param {Object} regexp The regexp to clone.
4629      * @returns {Object} Returns the cloned regexp.
4630      */
4631     function cloneRegExp(regexp) {
4632       var result = new regexp.constructor(regexp.source, reFlags.exec(regexp));
4633       result.lastIndex = regexp.lastIndex;
4634       return result;
4635     }
4636
4637     /**
4638      * Creates a clone of `set`.
4639      *
4640      * @private
4641      * @param {Object} set The set to clone.
4642      * @param {Function} cloneFunc The function to clone values.
4643      * @param {boolean} [isDeep] Specify a deep clone.
4644      * @returns {Object} Returns the cloned set.
4645      */
4646     function cloneSet(set, isDeep, cloneFunc) {
4647       var array = isDeep ? cloneFunc(setToArray(set), CLONE_DEEP_FLAG) : setToArray(set);
4648       return arrayReduce(array, addSetEntry, new set.constructor);
4649     }
4650
4651     /**
4652      * Creates a clone of the `symbol` object.
4653      *
4654      * @private
4655      * @param {Object} symbol The symbol object to clone.
4656      * @returns {Object} Returns the cloned symbol object.
4657      */
4658     function cloneSymbol(symbol) {
4659       return symbolValueOf ? Object(symbolValueOf.call(symbol)) : {};
4660     }
4661
4662     /**
4663      * Creates a clone of `typedArray`.
4664      *
4665      * @private
4666      * @param {Object} typedArray The typed array to clone.
4667      * @param {boolean} [isDeep] Specify a deep clone.
4668      * @returns {Object} Returns the cloned typed array.
4669      */
4670     function cloneTypedArray(typedArray, isDeep) {
4671       var buffer = isDeep ? cloneArrayBuffer(typedArray.buffer) : typedArray.buffer;
4672       return new typedArray.constructor(buffer, typedArray.byteOffset, typedArray.length);
4673     }
4674
4675     /**
4676      * Compares values to sort them in ascending order.
4677      *
4678      * @private
4679      * @param {*} value The value to compare.
4680      * @param {*} other The other value to compare.
4681      * @returns {number} Returns the sort order indicator for `value`.
4682      */
4683     function compareAscending(value, other) {
4684       if (value !== other) {
4685         var valIsDefined = value !== undefined,
4686             valIsNull = value === null,
4687             valIsReflexive = value === value,
4688             valIsSymbol = isSymbol(value);
4689
4690         var othIsDefined = other !== undefined,
4691             othIsNull = other === null,
4692             othIsReflexive = other === other,
4693             othIsSymbol = isSymbol(other);
4694
4695         if ((!othIsNull && !othIsSymbol && !valIsSymbol && value > other) ||
4696             (valIsSymbol && othIsDefined && othIsReflexive && !othIsNull && !othIsSymbol) ||
4697             (valIsNull && othIsDefined && othIsReflexive) ||
4698             (!valIsDefined && othIsReflexive) ||
4699             !valIsReflexive) {
4700           return 1;
4701         }
4702         if ((!valIsNull && !valIsSymbol && !othIsSymbol && value < other) ||
4703             (othIsSymbol && valIsDefined && valIsReflexive && !valIsNull && !valIsSymbol) ||
4704             (othIsNull && valIsDefined && valIsReflexive) ||
4705             (!othIsDefined && valIsReflexive) ||
4706             !othIsReflexive) {
4707           return -1;
4708         }
4709       }
4710       return 0;
4711     }
4712
4713     /**
4714      * Used by `_.orderBy` to compare multiple properties of a value to another
4715      * and stable sort them.
4716      *
4717      * If `orders` is unspecified, all values are sorted in ascending order. Otherwise,
4718      * specify an order of "desc" for descending or "asc" for ascending sort order
4719      * of corresponding values.
4720      *
4721      * @private
4722      * @param {Object} object The object to compare.
4723      * @param {Object} other The other object to compare.
4724      * @param {boolean[]|string[]} orders The order to sort by for each property.
4725      * @returns {number} Returns the sort order indicator for `object`.
4726      */
4727     function compareMultiple(object, other, orders) {
4728       var index = -1,
4729           objCriteria = object.criteria,
4730           othCriteria = other.criteria,
4731           length = objCriteria.length,
4732           ordersLength = orders.length;
4733
4734       while (++index < length) {
4735         var result = compareAscending(objCriteria[index], othCriteria[index]);
4736         if (result) {
4737           if (index >= ordersLength) {
4738             return result;
4739           }
4740           var order = orders[index];
4741           return result * (order == 'desc' ? -1 : 1);
4742         }
4743       }
4744       // Fixes an `Array#sort` bug in the JS engine embedded in Adobe applications
4745       // that causes it, under certain circumstances, to provide the same value for
4746       // `object` and `other`. See https://github.com/jashkenas/underscore/pull/1247
4747       // for more details.
4748       //
4749       // This also ensures a stable sort in V8 and other engines.
4750       // See https://bugs.chromium.org/p/v8/issues/detail?id=90 for more details.
4751       return object.index - other.index;
4752     }
4753
4754     /**
4755      * Creates an array that is the composition of partially applied arguments,
4756      * placeholders, and provided arguments into a single array of arguments.
4757      *
4758      * @private
4759      * @param {Array} args The provided arguments.
4760      * @param {Array} partials The arguments to prepend to those provided.
4761      * @param {Array} holders The `partials` placeholder indexes.
4762      * @params {boolean} [isCurried] Specify composing for a curried function.
4763      * @returns {Array} Returns the new array of composed arguments.
4764      */
4765     function composeArgs(args, partials, holders, isCurried) {
4766       var argsIndex = -1,
4767           argsLength = args.length,
4768           holdersLength = holders.length,
4769           leftIndex = -1,
4770           leftLength = partials.length,
4771           rangeLength = nativeMax(argsLength - holdersLength, 0),
4772           result = Array(leftLength + rangeLength),
4773           isUncurried = !isCurried;
4774
4775       while (++leftIndex < leftLength) {
4776         result[leftIndex] = partials[leftIndex];
4777       }
4778       while (++argsIndex < holdersLength) {
4779         if (isUncurried || argsIndex < argsLength) {
4780           result[holders[argsIndex]] = args[argsIndex];
4781         }
4782       }
4783       while (rangeLength--) {
4784         result[leftIndex++] = args[argsIndex++];
4785       }
4786       return result;
4787     }
4788
4789     /**
4790      * This function is like `composeArgs` except that the arguments composition
4791      * is tailored for `_.partialRight`.
4792      *
4793      * @private
4794      * @param {Array} args The provided arguments.
4795      * @param {Array} partials The arguments to append to those provided.
4796      * @param {Array} holders The `partials` placeholder indexes.
4797      * @params {boolean} [isCurried] Specify composing for a curried function.
4798      * @returns {Array} Returns the new array of composed arguments.
4799      */
4800     function composeArgsRight(args, partials, holders, isCurried) {
4801       var argsIndex = -1,
4802           argsLength = args.length,
4803           holdersIndex = -1,
4804           holdersLength = holders.length,
4805           rightIndex = -1,
4806           rightLength = partials.length,
4807           rangeLength = nativeMax(argsLength - holdersLength, 0),
4808           result = Array(rangeLength + rightLength),
4809           isUncurried = !isCurried;
4810
4811       while (++argsIndex < rangeLength) {
4812         result[argsIndex] = args[argsIndex];
4813       }
4814       var offset = argsIndex;
4815       while (++rightIndex < rightLength) {
4816         result[offset + rightIndex] = partials[rightIndex];
4817       }
4818       while (++holdersIndex < holdersLength) {
4819         if (isUncurried || argsIndex < argsLength) {
4820           result[offset + holders[holdersIndex]] = args[argsIndex++];
4821         }
4822       }
4823       return result;
4824     }
4825
4826     /**
4827      * Copies the values of `source` to `array`.
4828      *
4829      * @private
4830      * @param {Array} source The array to copy values from.
4831      * @param {Array} [array=[]] The array to copy values to.
4832      * @returns {Array} Returns `array`.
4833      */
4834     function copyArray(source, array) {
4835       var index = -1,
4836           length = source.length;
4837
4838       array || (array = Array(length));
4839       while (++index < length) {
4840         array[index] = source[index];
4841       }
4842       return array;
4843     }
4844
4845     /**
4846      * Copies properties of `source` to `object`.
4847      *
4848      * @private
4849      * @param {Object} source The object to copy properties from.
4850      * @param {Array} props The property identifiers to copy.
4851      * @param {Object} [object={}] The object to copy properties to.
4852      * @param {Function} [customizer] The function to customize copied values.
4853      * @returns {Object} Returns `object`.
4854      */
4855     function copyObject(source, props, object, customizer) {
4856       var isNew = !object;
4857       object || (object = {});
4858
4859       var index = -1,
4860           length = props.length;
4861
4862       while (++index < length) {
4863         var key = props[index];
4864
4865         var newValue = customizer
4866           ? customizer(object[key], source[key], key, object, source)
4867           : undefined;
4868
4869         if (newValue === undefined) {
4870           newValue = source[key];
4871         }
4872         if (isNew) {
4873           baseAssignValue(object, key, newValue);
4874         } else {
4875           assignValue(object, key, newValue);
4876         }
4877       }
4878       return object;
4879     }
4880
4881     /**
4882      * Copies own symbols of `source` to `object`.
4883      *
4884      * @private
4885      * @param {Object} source The object to copy symbols from.
4886      * @param {Object} [object={}] The object to copy symbols to.
4887      * @returns {Object} Returns `object`.
4888      */
4889     function copySymbols(source, object) {
4890       return copyObject(source, getSymbols(source), object);
4891     }
4892
4893     /**
4894      * Copies own and inherited symbols of `source` to `object`.
4895      *
4896      * @private
4897      * @param {Object} source The object to copy symbols from.
4898      * @param {Object} [object={}] The object to copy symbols to.
4899      * @returns {Object} Returns `object`.
4900      */
4901     function copySymbolsIn(source, object) {
4902       return copyObject(source, getSymbolsIn(source), object);
4903     }
4904
4905     /**
4906      * Creates a function like `_.groupBy`.
4907      *
4908      * @private
4909      * @param {Function} setter The function to set accumulator values.
4910      * @param {Function} [initializer] The accumulator object initializer.
4911      * @returns {Function} Returns the new aggregator function.
4912      */
4913     function createAggregator(setter, initializer) {
4914       return function(collection, iteratee) {
4915         var func = isArray(collection) ? arrayAggregator : baseAggregator,
4916             accumulator = initializer ? initializer() : {};
4917
4918         return func(collection, setter, getIteratee(iteratee, 2), accumulator);
4919       };
4920     }
4921
4922     /**
4923      * Creates a function like `_.assign`.
4924      *
4925      * @private
4926      * @param {Function} assigner The function to assign values.
4927      * @returns {Function} Returns the new assigner function.
4928      */
4929     function createAssigner(assigner) {
4930       return baseRest(function(object, sources) {
4931         var index = -1,
4932             length = sources.length,
4933             customizer = length > 1 ? sources[length - 1] : undefined,
4934             guard = length > 2 ? sources[2] : undefined;
4935
4936         customizer = (assigner.length > 3 && typeof customizer == 'function')
4937           ? (length--, customizer)
4938           : undefined;
4939
4940         if (guard && isIterateeCall(sources[0], sources[1], guard)) {
4941           customizer = length < 3 ? undefined : customizer;
4942           length = 1;
4943         }
4944         object = Object(object);
4945         while (++index < length) {
4946           var source = sources[index];
4947           if (source) {
4948             assigner(object, source, index, customizer);
4949           }
4950         }
4951         return object;
4952       });
4953     }
4954
4955     /**
4956      * Creates a `baseEach` or `baseEachRight` function.
4957      *
4958      * @private
4959      * @param {Function} eachFunc The function to iterate over a collection.
4960      * @param {boolean} [fromRight] Specify iterating from right to left.
4961      * @returns {Function} Returns the new base function.
4962      */
4963     function createBaseEach(eachFunc, fromRight) {
4964       return function(collection, iteratee) {
4965         if (collection == null) {
4966           return collection;
4967         }
4968         if (!isArrayLike(collection)) {
4969           return eachFunc(collection, iteratee);
4970         }
4971         var length = collection.length,
4972             index = fromRight ? length : -1,
4973             iterable = Object(collection);
4974
4975         while ((fromRight ? index-- : ++index < length)) {
4976           if (iteratee(iterable[index], index, iterable) === false) {
4977             break;
4978           }
4979         }
4980         return collection;
4981       };
4982     }
4983
4984     /**
4985      * Creates a base function for methods like `_.forIn` and `_.forOwn`.
4986      *
4987      * @private
4988      * @param {boolean} [fromRight] Specify iterating from right to left.
4989      * @returns {Function} Returns the new base function.
4990      */
4991     function createBaseFor(fromRight) {
4992       return function(object, iteratee, keysFunc) {
4993         var index = -1,
4994             iterable = Object(object),
4995             props = keysFunc(object),
4996             length = props.length;
4997
4998         while (length--) {
4999           var key = props[fromRight ? length : ++index];
5000           if (iteratee(iterable[key], key, iterable) === false) {
5001             break;
5002           }
5003         }
5004         return object;
5005       };
5006     }
5007
5008     /**
5009      * Creates a function that wraps `func` to invoke it with the optional `this`
5010      * binding of `thisArg`.
5011      *
5012      * @private
5013      * @param {Function} func The function to wrap.
5014      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5015      * @param {*} [thisArg] The `this` binding of `func`.
5016      * @returns {Function} Returns the new wrapped function.
5017      */
5018     function createBind(func, bitmask, thisArg) {
5019       var isBind = bitmask & WRAP_BIND_FLAG,
5020           Ctor = createCtor(func);
5021
5022       function wrapper() {
5023         var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
5024         return fn.apply(isBind ? thisArg : this, arguments);
5025       }
5026       return wrapper;
5027     }
5028
5029     /**
5030      * Creates a function like `_.lowerFirst`.
5031      *
5032      * @private
5033      * @param {string} methodName The name of the `String` case method to use.
5034      * @returns {Function} Returns the new case function.
5035      */
5036     function createCaseFirst(methodName) {
5037       return function(string) {
5038         string = toString(string);
5039
5040         var strSymbols = hasUnicode(string)
5041           ? stringToArray(string)
5042           : undefined;
5043
5044         var chr = strSymbols
5045           ? strSymbols[0]
5046           : string.charAt(0);
5047
5048         var trailing = strSymbols
5049           ? castSlice(strSymbols, 1).join('')
5050           : string.slice(1);
5051
5052         return chr[methodName]() + trailing;
5053       };
5054     }
5055
5056     /**
5057      * Creates a function like `_.camelCase`.
5058      *
5059      * @private
5060      * @param {Function} callback The function to combine each word.
5061      * @returns {Function} Returns the new compounder function.
5062      */
5063     function createCompounder(callback) {
5064       return function(string) {
5065         return arrayReduce(words(deburr(string).replace(reApos, '')), callback, '');
5066       };
5067     }
5068
5069     /**
5070      * Creates a function that produces an instance of `Ctor` regardless of
5071      * whether it was invoked as part of a `new` expression or by `call` or `apply`.
5072      *
5073      * @private
5074      * @param {Function} Ctor The constructor to wrap.
5075      * @returns {Function} Returns the new wrapped function.
5076      */
5077     function createCtor(Ctor) {
5078       return function() {
5079         // Use a `switch` statement to work with class constructors. See
5080         // http://ecma-international.org/ecma-262/7.0/#sec-ecmascript-function-objects-call-thisargument-argumentslist
5081         // for more details.
5082         var args = arguments;
5083         switch (args.length) {
5084           case 0: return new Ctor;
5085           case 1: return new Ctor(args[0]);
5086           case 2: return new Ctor(args[0], args[1]);
5087           case 3: return new Ctor(args[0], args[1], args[2]);
5088           case 4: return new Ctor(args[0], args[1], args[2], args[3]);
5089           case 5: return new Ctor(args[0], args[1], args[2], args[3], args[4]);
5090           case 6: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5]);
5091           case 7: return new Ctor(args[0], args[1], args[2], args[3], args[4], args[5], args[6]);
5092         }
5093         var thisBinding = baseCreate(Ctor.prototype),
5094             result = Ctor.apply(thisBinding, args);
5095
5096         // Mimic the constructor's `return` behavior.
5097         // See https://es5.github.io/#x13.2.2 for more details.
5098         return isObject(result) ? result : thisBinding;
5099       };
5100     }
5101
5102     /**
5103      * Creates a function that wraps `func` to enable currying.
5104      *
5105      * @private
5106      * @param {Function} func The function to wrap.
5107      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5108      * @param {number} arity The arity of `func`.
5109      * @returns {Function} Returns the new wrapped function.
5110      */
5111     function createCurry(func, bitmask, arity) {
5112       var Ctor = createCtor(func);
5113
5114       function wrapper() {
5115         var length = arguments.length,
5116             args = Array(length),
5117             index = length,
5118             placeholder = getHolder(wrapper);
5119
5120         while (index--) {
5121           args[index] = arguments[index];
5122         }
5123         var holders = (length < 3 && args[0] !== placeholder && args[length - 1] !== placeholder)
5124           ? []
5125           : replaceHolders(args, placeholder);
5126
5127         length -= holders.length;
5128         if (length < arity) {
5129           return createRecurry(
5130             func, bitmask, createHybrid, wrapper.placeholder, undefined,
5131             args, holders, undefined, undefined, arity - length);
5132         }
5133         var fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
5134         return apply(fn, this, args);
5135       }
5136       return wrapper;
5137     }
5138
5139     /**
5140      * Creates a `_.find` or `_.findLast` function.
5141      *
5142      * @private
5143      * @param {Function} findIndexFunc The function to find the collection index.
5144      * @returns {Function} Returns the new find function.
5145      */
5146     function createFind(findIndexFunc) {
5147       return function(collection, predicate, fromIndex) {
5148         var iterable = Object(collection);
5149         if (!isArrayLike(collection)) {
5150           var iteratee = getIteratee(predicate, 3);
5151           collection = keys(collection);
5152           predicate = function(key) { return iteratee(iterable[key], key, iterable); };
5153         }
5154         var index = findIndexFunc(collection, predicate, fromIndex);
5155         return index > -1 ? iterable[iteratee ? collection[index] : index] : undefined;
5156       };
5157     }
5158
5159     /**
5160      * Creates a `_.flow` or `_.flowRight` function.
5161      *
5162      * @private
5163      * @param {boolean} [fromRight] Specify iterating from right to left.
5164      * @returns {Function} Returns the new flow function.
5165      */
5166     function createFlow(fromRight) {
5167       return flatRest(function(funcs) {
5168         var length = funcs.length,
5169             index = length,
5170             prereq = LodashWrapper.prototype.thru;
5171
5172         if (fromRight) {
5173           funcs.reverse();
5174         }
5175         while (index--) {
5176           var func = funcs[index];
5177           if (typeof func != 'function') {
5178             throw new TypeError(FUNC_ERROR_TEXT);
5179           }
5180           if (prereq && !wrapper && getFuncName(func) == 'wrapper') {
5181             var wrapper = new LodashWrapper([], true);
5182           }
5183         }
5184         index = wrapper ? index : length;
5185         while (++index < length) {
5186           func = funcs[index];
5187
5188           var funcName = getFuncName(func),
5189               data = funcName == 'wrapper' ? getData(func) : undefined;
5190
5191           if (data && isLaziable(data[0]) &&
5192                 data[1] == (WRAP_ARY_FLAG | WRAP_CURRY_FLAG | WRAP_PARTIAL_FLAG | WRAP_REARG_FLAG) &&
5193                 !data[4].length && data[9] == 1
5194               ) {
5195             wrapper = wrapper[getFuncName(data[0])].apply(wrapper, data[3]);
5196           } else {
5197             wrapper = (func.length == 1 && isLaziable(func))
5198               ? wrapper[funcName]()
5199               : wrapper.thru(func);
5200           }
5201         }
5202         return function() {
5203           var args = arguments,
5204               value = args[0];
5205
5206           if (wrapper && args.length == 1 &&
5207               isArray(value) && value.length >= LARGE_ARRAY_SIZE) {
5208             return wrapper.plant(value).value();
5209           }
5210           var index = 0,
5211               result = length ? funcs[index].apply(this, args) : value;
5212
5213           while (++index < length) {
5214             result = funcs[index].call(this, result);
5215           }
5216           return result;
5217         };
5218       });
5219     }
5220
5221     /**
5222      * Creates a function that wraps `func` to invoke it with optional `this`
5223      * binding of `thisArg`, partial application, and currying.
5224      *
5225      * @private
5226      * @param {Function|string} func The function or method name to wrap.
5227      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5228      * @param {*} [thisArg] The `this` binding of `func`.
5229      * @param {Array} [partials] The arguments to prepend to those provided to
5230      *  the new function.
5231      * @param {Array} [holders] The `partials` placeholder indexes.
5232      * @param {Array} [partialsRight] The arguments to append to those provided
5233      *  to the new function.
5234      * @param {Array} [holdersRight] The `partialsRight` placeholder indexes.
5235      * @param {Array} [argPos] The argument positions of the new function.
5236      * @param {number} [ary] The arity cap of `func`.
5237      * @param {number} [arity] The arity of `func`.
5238      * @returns {Function} Returns the new wrapped function.
5239      */
5240     function createHybrid(func, bitmask, thisArg, partials, holders, partialsRight, holdersRight, argPos, ary, arity) {
5241       var isAry = bitmask & WRAP_ARY_FLAG,
5242           isBind = bitmask & WRAP_BIND_FLAG,
5243           isBindKey = bitmask & WRAP_BIND_KEY_FLAG,
5244           isCurried = bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG),
5245           isFlip = bitmask & WRAP_FLIP_FLAG,
5246           Ctor = isBindKey ? undefined : createCtor(func);
5247
5248       function wrapper() {
5249         var length = arguments.length,
5250             args = Array(length),
5251             index = length;
5252
5253         while (index--) {
5254           args[index] = arguments[index];
5255         }
5256         if (isCurried) {
5257           var placeholder = getHolder(wrapper),
5258               holdersCount = countHolders(args, placeholder);
5259         }
5260         if (partials) {
5261           args = composeArgs(args, partials, holders, isCurried);
5262         }
5263         if (partialsRight) {
5264           args = composeArgsRight(args, partialsRight, holdersRight, isCurried);
5265         }
5266         length -= holdersCount;
5267         if (isCurried && length < arity) {
5268           var newHolders = replaceHolders(args, placeholder);
5269           return createRecurry(
5270             func, bitmask, createHybrid, wrapper.placeholder, thisArg,
5271             args, newHolders, argPos, ary, arity - length
5272           );
5273         }
5274         var thisBinding = isBind ? thisArg : this,
5275             fn = isBindKey ? thisBinding[func] : func;
5276
5277         length = args.length;
5278         if (argPos) {
5279           args = reorder(args, argPos);
5280         } else if (isFlip && length > 1) {
5281           args.reverse();
5282         }
5283         if (isAry && ary < length) {
5284           args.length = ary;
5285         }
5286         if (this && this !== root && this instanceof wrapper) {
5287           fn = Ctor || createCtor(fn);
5288         }
5289         return fn.apply(thisBinding, args);
5290       }
5291       return wrapper;
5292     }
5293
5294     /**
5295      * Creates a function like `_.invertBy`.
5296      *
5297      * @private
5298      * @param {Function} setter The function to set accumulator values.
5299      * @param {Function} toIteratee The function to resolve iteratees.
5300      * @returns {Function} Returns the new inverter function.
5301      */
5302     function createInverter(setter, toIteratee) {
5303       return function(object, iteratee) {
5304         return baseInverter(object, setter, toIteratee(iteratee), {});
5305       };
5306     }
5307
5308     /**
5309      * Creates a function that performs a mathematical operation on two values.
5310      *
5311      * @private
5312      * @param {Function} operator The function to perform the operation.
5313      * @param {number} [defaultValue] The value used for `undefined` arguments.
5314      * @returns {Function} Returns the new mathematical operation function.
5315      */
5316     function createMathOperation(operator, defaultValue) {
5317       return function(value, other) {
5318         var result;
5319         if (value === undefined && other === undefined) {
5320           return defaultValue;
5321         }
5322         if (value !== undefined) {
5323           result = value;
5324         }
5325         if (other !== undefined) {
5326           if (result === undefined) {
5327             return other;
5328           }
5329           if (typeof value == 'string' || typeof other == 'string') {
5330             value = baseToString(value);
5331             other = baseToString(other);
5332           } else {
5333             value = baseToNumber(value);
5334             other = baseToNumber(other);
5335           }
5336           result = operator(value, other);
5337         }
5338         return result;
5339       };
5340     }
5341
5342     /**
5343      * Creates a function like `_.over`.
5344      *
5345      * @private
5346      * @param {Function} arrayFunc The function to iterate over iteratees.
5347      * @returns {Function} Returns the new over function.
5348      */
5349     function createOver(arrayFunc) {
5350       return flatRest(function(iteratees) {
5351         iteratees = arrayMap(iteratees, baseUnary(getIteratee()));
5352         return baseRest(function(args) {
5353           var thisArg = this;
5354           return arrayFunc(iteratees, function(iteratee) {
5355             return apply(iteratee, thisArg, args);
5356           });
5357         });
5358       });
5359     }
5360
5361     /**
5362      * Creates the padding for `string` based on `length`. The `chars` string
5363      * is truncated if the number of characters exceeds `length`.
5364      *
5365      * @private
5366      * @param {number} length The padding length.
5367      * @param {string} [chars=' '] The string used as padding.
5368      * @returns {string} Returns the padding for `string`.
5369      */
5370     function createPadding(length, chars) {
5371       chars = chars === undefined ? ' ' : baseToString(chars);
5372
5373       var charsLength = chars.length;
5374       if (charsLength < 2) {
5375         return charsLength ? baseRepeat(chars, length) : chars;
5376       }
5377       var result = baseRepeat(chars, nativeCeil(length / stringSize(chars)));
5378       return hasUnicode(chars)
5379         ? castSlice(stringToArray(result), 0, length).join('')
5380         : result.slice(0, length);
5381     }
5382
5383     /**
5384      * Creates a function that wraps `func` to invoke it with the `this` binding
5385      * of `thisArg` and `partials` prepended to the arguments it receives.
5386      *
5387      * @private
5388      * @param {Function} func The function to wrap.
5389      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5390      * @param {*} thisArg The `this` binding of `func`.
5391      * @param {Array} partials The arguments to prepend to those provided to
5392      *  the new function.
5393      * @returns {Function} Returns the new wrapped function.
5394      */
5395     function createPartial(func, bitmask, thisArg, partials) {
5396       var isBind = bitmask & WRAP_BIND_FLAG,
5397           Ctor = createCtor(func);
5398
5399       function wrapper() {
5400         var argsIndex = -1,
5401             argsLength = arguments.length,
5402             leftIndex = -1,
5403             leftLength = partials.length,
5404             args = Array(leftLength + argsLength),
5405             fn = (this && this !== root && this instanceof wrapper) ? Ctor : func;
5406
5407         while (++leftIndex < leftLength) {
5408           args[leftIndex] = partials[leftIndex];
5409         }
5410         while (argsLength--) {
5411           args[leftIndex++] = arguments[++argsIndex];
5412         }
5413         return apply(fn, isBind ? thisArg : this, args);
5414       }
5415       return wrapper;
5416     }
5417
5418     /**
5419      * Creates a `_.range` or `_.rangeRight` function.
5420      *
5421      * @private
5422      * @param {boolean} [fromRight] Specify iterating from right to left.
5423      * @returns {Function} Returns the new range function.
5424      */
5425     function createRange(fromRight) {
5426       return function(start, end, step) {
5427         if (step && typeof step != 'number' && isIterateeCall(start, end, step)) {
5428           end = step = undefined;
5429         }
5430         // Ensure the sign of `-0` is preserved.
5431         start = toFinite(start);
5432         if (end === undefined) {
5433           end = start;
5434           start = 0;
5435         } else {
5436           end = toFinite(end);
5437         }
5438         step = step === undefined ? (start < end ? 1 : -1) : toFinite(step);
5439         return baseRange(start, end, step, fromRight);
5440       };
5441     }
5442
5443     /**
5444      * Creates a function that performs a relational operation on two values.
5445      *
5446      * @private
5447      * @param {Function} operator The function to perform the operation.
5448      * @returns {Function} Returns the new relational operation function.
5449      */
5450     function createRelationalOperation(operator) {
5451       return function(value, other) {
5452         if (!(typeof value == 'string' && typeof other == 'string')) {
5453           value = toNumber(value);
5454           other = toNumber(other);
5455         }
5456         return operator(value, other);
5457       };
5458     }
5459
5460     /**
5461      * Creates a function that wraps `func` to continue currying.
5462      *
5463      * @private
5464      * @param {Function} func The function to wrap.
5465      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
5466      * @param {Function} wrapFunc The function to create the `func` wrapper.
5467      * @param {*} placeholder The placeholder value.
5468      * @param {*} [thisArg] The `this` binding of `func`.
5469      * @param {Array} [partials] The arguments to prepend to those provided to
5470      *  the new function.
5471      * @param {Array} [holders] The `partials` placeholder indexes.
5472      * @param {Array} [argPos] The argument positions of the new function.
5473      * @param {number} [ary] The arity cap of `func`.
5474      * @param {number} [arity] The arity of `func`.
5475      * @returns {Function} Returns the new wrapped function.
5476      */
5477     function createRecurry(func, bitmask, wrapFunc, placeholder, thisArg, partials, holders, argPos, ary, arity) {
5478       var isCurry = bitmask & WRAP_CURRY_FLAG,
5479           newHolders = isCurry ? holders : undefined,
5480           newHoldersRight = isCurry ? undefined : holders,
5481           newPartials = isCurry ? partials : undefined,
5482           newPartialsRight = isCurry ? undefined : partials;
5483
5484       bitmask |= (isCurry ? WRAP_PARTIAL_FLAG : WRAP_PARTIAL_RIGHT_FLAG);
5485       bitmask &= ~(isCurry ? WRAP_PARTIAL_RIGHT_FLAG : WRAP_PARTIAL_FLAG);
5486
5487       if (!(bitmask & WRAP_CURRY_BOUND_FLAG)) {
5488         bitmask &= ~(WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG);
5489       }
5490       var newData = [
5491         func, bitmask, thisArg, newPartials, newHolders, newPartialsRight,
5492         newHoldersRight, argPos, ary, arity
5493       ];
5494
5495       var result = wrapFunc.apply(undefined, newData);
5496       if (isLaziable(func)) {
5497         setData(result, newData);
5498       }
5499       result.placeholder = placeholder;
5500       return setWrapToString(result, func, bitmask);
5501     }
5502
5503     /**
5504      * Creates a function like `_.round`.
5505      *
5506      * @private
5507      * @param {string} methodName The name of the `Math` method to use when rounding.
5508      * @returns {Function} Returns the new round function.
5509      */
5510     function createRound(methodName) {
5511       var func = Math[methodName];
5512       return function(number, precision) {
5513         number = toNumber(number);
5514         precision = nativeMin(toInteger(precision), 292);
5515         if (precision) {
5516           // Shift with exponential notation to avoid floating-point issues.
5517           // See [MDN](https://mdn.io/round#Examples) for more details.
5518           var pair = (toString(number) + 'e').split('e'),
5519               value = func(pair[0] + 'e' + (+pair[1] + precision));
5520
5521           pair = (toString(value) + 'e').split('e');
5522           return +(pair[0] + 'e' + (+pair[1] - precision));
5523         }
5524         return func(number);
5525       };
5526     }
5527
5528     /**
5529      * Creates a set object of `values`.
5530      *
5531      * @private
5532      * @param {Array} values The values to add to the set.
5533      * @returns {Object} Returns the new set.
5534      */
5535     var createSet = !(Set && (1 / setToArray(new Set([,-0]))[1]) == INFINITY) ? noop : function(values) {
5536       return new Set(values);
5537     };
5538
5539     /**
5540      * Creates a `_.toPairs` or `_.toPairsIn` function.
5541      *
5542      * @private
5543      * @param {Function} keysFunc The function to get the keys of a given object.
5544      * @returns {Function} Returns the new pairs function.
5545      */
5546     function createToPairs(keysFunc) {
5547       return function(object) {
5548         var tag = getTag(object);
5549         if (tag == mapTag) {
5550           return mapToArray(object);
5551         }
5552         if (tag == setTag) {
5553           return setToPairs(object);
5554         }
5555         return baseToPairs(object, keysFunc(object));
5556       };
5557     }
5558
5559     /**
5560      * Creates a function that either curries or invokes `func` with optional
5561      * `this` binding and partially applied arguments.
5562      *
5563      * @private
5564      * @param {Function|string} func The function or method name to wrap.
5565      * @param {number} bitmask The bitmask flags.
5566      *    1 - `_.bind`
5567      *    2 - `_.bindKey`
5568      *    4 - `_.curry` or `_.curryRight` of a bound function
5569      *    8 - `_.curry`
5570      *   16 - `_.curryRight`
5571      *   32 - `_.partial`
5572      *   64 - `_.partialRight`
5573      *  128 - `_.rearg`
5574      *  256 - `_.ary`
5575      *  512 - `_.flip`
5576      * @param {*} [thisArg] The `this` binding of `func`.
5577      * @param {Array} [partials] The arguments to be partially applied.
5578      * @param {Array} [holders] The `partials` placeholder indexes.
5579      * @param {Array} [argPos] The argument positions of the new function.
5580      * @param {number} [ary] The arity cap of `func`.
5581      * @param {number} [arity] The arity of `func`.
5582      * @returns {Function} Returns the new wrapped function.
5583      */
5584     function createWrap(func, bitmask, thisArg, partials, holders, argPos, ary, arity) {
5585       var isBindKey = bitmask & WRAP_BIND_KEY_FLAG;
5586       if (!isBindKey && typeof func != 'function') {
5587         throw new TypeError(FUNC_ERROR_TEXT);
5588       }
5589       var length = partials ? partials.length : 0;
5590       if (!length) {
5591         bitmask &= ~(WRAP_PARTIAL_FLAG | WRAP_PARTIAL_RIGHT_FLAG);
5592         partials = holders = undefined;
5593       }
5594       ary = ary === undefined ? ary : nativeMax(toInteger(ary), 0);
5595       arity = arity === undefined ? arity : toInteger(arity);
5596       length -= holders ? holders.length : 0;
5597
5598       if (bitmask & WRAP_PARTIAL_RIGHT_FLAG) {
5599         var partialsRight = partials,
5600             holdersRight = holders;
5601
5602         partials = holders = undefined;
5603       }
5604       var data = isBindKey ? undefined : getData(func);
5605
5606       var newData = [
5607         func, bitmask, thisArg, partials, holders, partialsRight, holdersRight,
5608         argPos, ary, arity
5609       ];
5610
5611       if (data) {
5612         mergeData(newData, data);
5613       }
5614       func = newData[0];
5615       bitmask = newData[1];
5616       thisArg = newData[2];
5617       partials = newData[3];
5618       holders = newData[4];
5619       arity = newData[9] = newData[9] == null
5620         ? (isBindKey ? 0 : func.length)
5621         : nativeMax(newData[9] - length, 0);
5622
5623       if (!arity && bitmask & (WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG)) {
5624         bitmask &= ~(WRAP_CURRY_FLAG | WRAP_CURRY_RIGHT_FLAG);
5625       }
5626       if (!bitmask || bitmask == WRAP_BIND_FLAG) {
5627         var result = createBind(func, bitmask, thisArg);
5628       } else if (bitmask == WRAP_CURRY_FLAG || bitmask == WRAP_CURRY_RIGHT_FLAG) {
5629         result = createCurry(func, bitmask, arity);
5630       } else if ((bitmask == WRAP_PARTIAL_FLAG || bitmask == (WRAP_BIND_FLAG | WRAP_PARTIAL_FLAG)) && !holders.length) {
5631         result = createPartial(func, bitmask, thisArg, partials);
5632       } else {
5633         result = createHybrid.apply(undefined, newData);
5634       }
5635       var setter = data ? baseSetData : setData;
5636       return setWrapToString(setter(result, newData), func, bitmask);
5637     }
5638
5639     /**
5640      * A specialized version of `baseIsEqualDeep` for arrays with support for
5641      * partial deep comparisons.
5642      *
5643      * @private
5644      * @param {Array} array The array to compare.
5645      * @param {Array} other The other array to compare.
5646      * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
5647      * @param {Function} customizer The function to customize comparisons.
5648      * @param {Function} equalFunc The function to determine equivalents of values.
5649      * @param {Object} stack Tracks traversed `array` and `other` objects.
5650      * @returns {boolean} Returns `true` if the arrays are equivalent, else `false`.
5651      */
5652     function equalArrays(array, other, bitmask, customizer, equalFunc, stack) {
5653       var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
5654           arrLength = array.length,
5655           othLength = other.length;
5656
5657       if (arrLength != othLength && !(isPartial && othLength > arrLength)) {
5658         return false;
5659       }
5660       // Assume cyclic values are equal.
5661       var stacked = stack.get(array);
5662       if (stacked && stack.get(other)) {
5663         return stacked == other;
5664       }
5665       var index = -1,
5666           result = true,
5667           seen = (bitmask & COMPARE_UNORDERED_FLAG) ? new SetCache : undefined;
5668
5669       stack.set(array, other);
5670       stack.set(other, array);
5671
5672       // Ignore non-index properties.
5673       while (++index < arrLength) {
5674         var arrValue = array[index],
5675             othValue = other[index];
5676
5677         if (customizer) {
5678           var compared = isPartial
5679             ? customizer(othValue, arrValue, index, other, array, stack)
5680             : customizer(arrValue, othValue, index, array, other, stack);
5681         }
5682         if (compared !== undefined) {
5683           if (compared) {
5684             continue;
5685           }
5686           result = false;
5687           break;
5688         }
5689         // Recursively compare arrays (susceptible to call stack limits).
5690         if (seen) {
5691           if (!arraySome(other, function(othValue, othIndex) {
5692                 if (!cacheHas(seen, othIndex) &&
5693                     (arrValue === othValue || equalFunc(arrValue, othValue, bitmask, customizer, stack))) {
5694                   return seen.push(othIndex);
5695                 }
5696               })) {
5697             result = false;
5698             break;
5699           }
5700         } else if (!(
5701               arrValue === othValue ||
5702                 equalFunc(arrValue, othValue, bitmask, customizer, stack)
5703             )) {
5704           result = false;
5705           break;
5706         }
5707       }
5708       stack['delete'](array);
5709       stack['delete'](other);
5710       return result;
5711     }
5712
5713     /**
5714      * A specialized version of `baseIsEqualDeep` for comparing objects of
5715      * the same `toStringTag`.
5716      *
5717      * **Note:** This function only supports comparing values with tags of
5718      * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
5719      *
5720      * @private
5721      * @param {Object} object The object to compare.
5722      * @param {Object} other The other object to compare.
5723      * @param {string} tag The `toStringTag` of the objects to compare.
5724      * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
5725      * @param {Function} customizer The function to customize comparisons.
5726      * @param {Function} equalFunc The function to determine equivalents of values.
5727      * @param {Object} stack Tracks traversed `object` and `other` objects.
5728      * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
5729      */
5730     function equalByTag(object, other, tag, bitmask, customizer, equalFunc, stack) {
5731       switch (tag) {
5732         case dataViewTag:
5733           if ((object.byteLength != other.byteLength) ||
5734               (object.byteOffset != other.byteOffset)) {
5735             return false;
5736           }
5737           object = object.buffer;
5738           other = other.buffer;
5739
5740         case arrayBufferTag:
5741           if ((object.byteLength != other.byteLength) ||
5742               !equalFunc(new Uint8Array(object), new Uint8Array(other))) {
5743             return false;
5744           }
5745           return true;
5746
5747         case boolTag:
5748         case dateTag:
5749         case numberTag:
5750           // Coerce booleans to `1` or `0` and dates to milliseconds.
5751           // Invalid dates are coerced to `NaN`.
5752           return eq(+object, +other);
5753
5754         case errorTag:
5755           return object.name == other.name && object.message == other.message;
5756
5757         case regexpTag:
5758         case stringTag:
5759           // Coerce regexes to strings and treat strings, primitives and objects,
5760           // as equal. See http://www.ecma-international.org/ecma-262/7.0/#sec-regexp.prototype.tostring
5761           // for more details.
5762           return object == (other + '');
5763
5764         case mapTag:
5765           var convert = mapToArray;
5766
5767         case setTag:
5768           var isPartial = bitmask & COMPARE_PARTIAL_FLAG;
5769           convert || (convert = setToArray);
5770
5771           if (object.size != other.size && !isPartial) {
5772             return false;
5773           }
5774           // Assume cyclic values are equal.
5775           var stacked = stack.get(object);
5776           if (stacked) {
5777             return stacked == other;
5778           }
5779           bitmask |= COMPARE_UNORDERED_FLAG;
5780
5781           // Recursively compare objects (susceptible to call stack limits).
5782           stack.set(object, other);
5783           var result = equalArrays(convert(object), convert(other), bitmask, customizer, equalFunc, stack);
5784           stack['delete'](object);
5785           return result;
5786
5787         case symbolTag:
5788           if (symbolValueOf) {
5789             return symbolValueOf.call(object) == symbolValueOf.call(other);
5790           }
5791       }
5792       return false;
5793     }
5794
5795     /**
5796      * A specialized version of `baseIsEqualDeep` for objects with support for
5797      * partial deep comparisons.
5798      *
5799      * @private
5800      * @param {Object} object The object to compare.
5801      * @param {Object} other The other object to compare.
5802      * @param {number} bitmask The bitmask flags. See `baseIsEqual` for more details.
5803      * @param {Function} customizer The function to customize comparisons.
5804      * @param {Function} equalFunc The function to determine equivalents of values.
5805      * @param {Object} stack Tracks traversed `object` and `other` objects.
5806      * @returns {boolean} Returns `true` if the objects are equivalent, else `false`.
5807      */
5808     function equalObjects(object, other, bitmask, customizer, equalFunc, stack) {
5809       var isPartial = bitmask & COMPARE_PARTIAL_FLAG,
5810           objProps = keys(object),
5811           objLength = objProps.length,
5812           othProps = keys(other),
5813           othLength = othProps.length;
5814
5815       if (objLength != othLength && !isPartial) {
5816         return false;
5817       }
5818       var index = objLength;
5819       while (index--) {
5820         var key = objProps[index];
5821         if (!(isPartial ? key in other : hasOwnProperty.call(other, key))) {
5822           return false;
5823         }
5824       }
5825       // Assume cyclic values are equal.
5826       var stacked = stack.get(object);
5827       if (stacked && stack.get(other)) {
5828         return stacked == other;
5829       }
5830       var result = true;
5831       stack.set(object, other);
5832       stack.set(other, object);
5833
5834       var skipCtor = isPartial;
5835       while (++index < objLength) {
5836         key = objProps[index];
5837         var objValue = object[key],
5838             othValue = other[key];
5839
5840         if (customizer) {
5841           var compared = isPartial
5842             ? customizer(othValue, objValue, key, other, object, stack)
5843             : customizer(objValue, othValue, key, object, other, stack);
5844         }
5845         // Recursively compare objects (susceptible to call stack limits).
5846         if (!(compared === undefined
5847               ? (objValue === othValue || equalFunc(objValue, othValue, bitmask, customizer, stack))
5848               : compared
5849             )) {
5850           result = false;
5851           break;
5852         }
5853         skipCtor || (skipCtor = key == 'constructor');
5854       }
5855       if (result && !skipCtor) {
5856         var objCtor = object.constructor,
5857             othCtor = other.constructor;
5858
5859         // Non `Object` object instances with different constructors are not equal.
5860         if (objCtor != othCtor &&
5861             ('constructor' in object && 'constructor' in other) &&
5862             !(typeof objCtor == 'function' && objCtor instanceof objCtor &&
5863               typeof othCtor == 'function' && othCtor instanceof othCtor)) {
5864           result = false;
5865         }
5866       }
5867       stack['delete'](object);
5868       stack['delete'](other);
5869       return result;
5870     }
5871
5872     /**
5873      * A specialized version of `baseRest` which flattens the rest array.
5874      *
5875      * @private
5876      * @param {Function} func The function to apply a rest parameter to.
5877      * @returns {Function} Returns the new function.
5878      */
5879     function flatRest(func) {
5880       return setToString(overRest(func, undefined, flatten), func + '');
5881     }
5882
5883     /**
5884      * Creates an array of own enumerable property names and symbols of `object`.
5885      *
5886      * @private
5887      * @param {Object} object The object to query.
5888      * @returns {Array} Returns the array of property names and symbols.
5889      */
5890     function getAllKeys(object) {
5891       return baseGetAllKeys(object, keys, getSymbols);
5892     }
5893
5894     /**
5895      * Creates an array of own and inherited enumerable property names and
5896      * symbols of `object`.
5897      *
5898      * @private
5899      * @param {Object} object The object to query.
5900      * @returns {Array} Returns the array of property names and symbols.
5901      */
5902     function getAllKeysIn(object) {
5903       return baseGetAllKeys(object, keysIn, getSymbolsIn);
5904     }
5905
5906     /**
5907      * Gets metadata for `func`.
5908      *
5909      * @private
5910      * @param {Function} func The function to query.
5911      * @returns {*} Returns the metadata for `func`.
5912      */
5913     var getData = !metaMap ? noop : function(func) {
5914       return metaMap.get(func);
5915     };
5916
5917     /**
5918      * Gets the name of `func`.
5919      *
5920      * @private
5921      * @param {Function} func The function to query.
5922      * @returns {string} Returns the function name.
5923      */
5924     function getFuncName(func) {
5925       var result = (func.name + ''),
5926           array = realNames[result],
5927           length = hasOwnProperty.call(realNames, result) ? array.length : 0;
5928
5929       while (length--) {
5930         var data = array[length],
5931             otherFunc = data.func;
5932         if (otherFunc == null || otherFunc == func) {
5933           return data.name;
5934         }
5935       }
5936       return result;
5937     }
5938
5939     /**
5940      * Gets the argument placeholder value for `func`.
5941      *
5942      * @private
5943      * @param {Function} func The function to inspect.
5944      * @returns {*} Returns the placeholder value.
5945      */
5946     function getHolder(func) {
5947       var object = hasOwnProperty.call(lodash, 'placeholder') ? lodash : func;
5948       return object.placeholder;
5949     }
5950
5951     /**
5952      * Gets the appropriate "iteratee" function. If `_.iteratee` is customized,
5953      * this function returns the custom method, otherwise it returns `baseIteratee`.
5954      * If arguments are provided, the chosen function is invoked with them and
5955      * its result is returned.
5956      *
5957      * @private
5958      * @param {*} [value] The value to convert to an iteratee.
5959      * @param {number} [arity] The arity of the created iteratee.
5960      * @returns {Function} Returns the chosen function or its result.
5961      */
5962     function getIteratee() {
5963       var result = lodash.iteratee || iteratee;
5964       result = result === iteratee ? baseIteratee : result;
5965       return arguments.length ? result(arguments[0], arguments[1]) : result;
5966     }
5967
5968     /**
5969      * Gets the data for `map`.
5970      *
5971      * @private
5972      * @param {Object} map The map to query.
5973      * @param {string} key The reference key.
5974      * @returns {*} Returns the map data.
5975      */
5976     function getMapData(map, key) {
5977       var data = map.__data__;
5978       return isKeyable(key)
5979         ? data[typeof key == 'string' ? 'string' : 'hash']
5980         : data.map;
5981     }
5982
5983     /**
5984      * Gets the property names, values, and compare flags of `object`.
5985      *
5986      * @private
5987      * @param {Object} object The object to query.
5988      * @returns {Array} Returns the match data of `object`.
5989      */
5990     function getMatchData(object) {
5991       var result = keys(object),
5992           length = result.length;
5993
5994       while (length--) {
5995         var key = result[length],
5996             value = object[key];
5997
5998         result[length] = [key, value, isStrictComparable(value)];
5999       }
6000       return result;
6001     }
6002
6003     /**
6004      * Gets the native function at `key` of `object`.
6005      *
6006      * @private
6007      * @param {Object} object The object to query.
6008      * @param {string} key The key of the method to get.
6009      * @returns {*} Returns the function if it's native, else `undefined`.
6010      */
6011     function getNative(object, key) {
6012       var value = getValue(object, key);
6013       return baseIsNative(value) ? value : undefined;
6014     }
6015
6016     /**
6017      * A specialized version of `baseGetTag` which ignores `Symbol.toStringTag` values.
6018      *
6019      * @private
6020      * @param {*} value The value to query.
6021      * @returns {string} Returns the raw `toStringTag`.
6022      */
6023     function getRawTag(value) {
6024       var isOwn = hasOwnProperty.call(value, symToStringTag),
6025           tag = value[symToStringTag];
6026
6027       try {
6028         value[symToStringTag] = undefined;
6029         var unmasked = true;
6030       } catch (e) {}
6031
6032       var result = nativeObjectToString.call(value);
6033       if (unmasked) {
6034         if (isOwn) {
6035           value[symToStringTag] = tag;
6036         } else {
6037           delete value[symToStringTag];
6038         }
6039       }
6040       return result;
6041     }
6042
6043     /**
6044      * Creates an array of the own enumerable symbols of `object`.
6045      *
6046      * @private
6047      * @param {Object} object The object to query.
6048      * @returns {Array} Returns the array of symbols.
6049      */
6050     var getSymbols = nativeGetSymbols ? overArg(nativeGetSymbols, Object) : stubArray;
6051
6052     /**
6053      * Creates an array of the own and inherited enumerable symbols of `object`.
6054      *
6055      * @private
6056      * @param {Object} object The object to query.
6057      * @returns {Array} Returns the array of symbols.
6058      */
6059     var getSymbolsIn = !nativeGetSymbols ? stubArray : function(object) {
6060       var result = [];
6061       while (object) {
6062         arrayPush(result, getSymbols(object));
6063         object = getPrototype(object);
6064       }
6065       return result;
6066     };
6067
6068     /**
6069      * Gets the `toStringTag` of `value`.
6070      *
6071      * @private
6072      * @param {*} value The value to query.
6073      * @returns {string} Returns the `toStringTag`.
6074      */
6075     var getTag = baseGetTag;
6076
6077     // Fallback for data views, maps, sets, and weak maps in IE 11 and promises in Node.js < 6.
6078     if ((DataView && getTag(new DataView(new ArrayBuffer(1))) != dataViewTag) ||
6079         (Map && getTag(new Map) != mapTag) ||
6080         (Promise && getTag(Promise.resolve()) != promiseTag) ||
6081         (Set && getTag(new Set) != setTag) ||
6082         (WeakMap && getTag(new WeakMap) != weakMapTag)) {
6083       getTag = function(value) {
6084         var result = baseGetTag(value),
6085             Ctor = result == objectTag ? value.constructor : undefined,
6086             ctorString = Ctor ? toSource(Ctor) : '';
6087
6088         if (ctorString) {
6089           switch (ctorString) {
6090             case dataViewCtorString: return dataViewTag;
6091             case mapCtorString: return mapTag;
6092             case promiseCtorString: return promiseTag;
6093             case setCtorString: return setTag;
6094             case weakMapCtorString: return weakMapTag;
6095           }
6096         }
6097         return result;
6098       };
6099     }
6100
6101     /**
6102      * Gets the view, applying any `transforms` to the `start` and `end` positions.
6103      *
6104      * @private
6105      * @param {number} start The start of the view.
6106      * @param {number} end The end of the view.
6107      * @param {Array} transforms The transformations to apply to the view.
6108      * @returns {Object} Returns an object containing the `start` and `end`
6109      *  positions of the view.
6110      */
6111     function getView(start, end, transforms) {
6112       var index = -1,
6113           length = transforms.length;
6114
6115       while (++index < length) {
6116         var data = transforms[index],
6117             size = data.size;
6118
6119         switch (data.type) {
6120           case 'drop':      start += size; break;
6121           case 'dropRight': end -= size; break;
6122           case 'take':      end = nativeMin(end, start + size); break;
6123           case 'takeRight': start = nativeMax(start, end - size); break;
6124         }
6125       }
6126       return { 'start': start, 'end': end };
6127     }
6128
6129     /**
6130      * Extracts wrapper details from the `source` body comment.
6131      *
6132      * @private
6133      * @param {string} source The source to inspect.
6134      * @returns {Array} Returns the wrapper details.
6135      */
6136     function getWrapDetails(source) {
6137       var match = source.match(reWrapDetails);
6138       return match ? match[1].split(reSplitDetails) : [];
6139     }
6140
6141     /**
6142      * Checks if `path` exists on `object`.
6143      *
6144      * @private
6145      * @param {Object} object The object to query.
6146      * @param {Array|string} path The path to check.
6147      * @param {Function} hasFunc The function to check properties.
6148      * @returns {boolean} Returns `true` if `path` exists, else `false`.
6149      */
6150     function hasPath(object, path, hasFunc) {
6151       path = isKey(path, object) ? [path] : castPath(path);
6152
6153       var index = -1,
6154           length = path.length,
6155           result = false;
6156
6157       while (++index < length) {
6158         var key = toKey(path[index]);
6159         if (!(result = object != null && hasFunc(object, key))) {
6160           break;
6161         }
6162         object = object[key];
6163       }
6164       if (result || ++index != length) {
6165         return result;
6166       }
6167       length = object == null ? 0 : object.length;
6168       return !!length && isLength(length) && isIndex(key, length) &&
6169         (isArray(object) || isArguments(object));
6170     }
6171
6172     /**
6173      * Initializes an array clone.
6174      *
6175      * @private
6176      * @param {Array} array The array to clone.
6177      * @returns {Array} Returns the initialized clone.
6178      */
6179     function initCloneArray(array) {
6180       var length = array.length,
6181           result = array.constructor(length);
6182
6183       // Add properties assigned by `RegExp#exec`.
6184       if (length && typeof array[0] == 'string' && hasOwnProperty.call(array, 'index')) {
6185         result.index = array.index;
6186         result.input = array.input;
6187       }
6188       return result;
6189     }
6190
6191     /**
6192      * Initializes an object clone.
6193      *
6194      * @private
6195      * @param {Object} object The object to clone.
6196      * @returns {Object} Returns the initialized clone.
6197      */
6198     function initCloneObject(object) {
6199       return (typeof object.constructor == 'function' && !isPrototype(object))
6200         ? baseCreate(getPrototype(object))
6201         : {};
6202     }
6203
6204     /**
6205      * Initializes an object clone based on its `toStringTag`.
6206      *
6207      * **Note:** This function only supports cloning values with tags of
6208      * `Boolean`, `Date`, `Error`, `Number`, `RegExp`, or `String`.
6209      *
6210      * @private
6211      * @param {Object} object The object to clone.
6212      * @param {string} tag The `toStringTag` of the object to clone.
6213      * @param {Function} cloneFunc The function to clone values.
6214      * @param {boolean} [isDeep] Specify a deep clone.
6215      * @returns {Object} Returns the initialized clone.
6216      */
6217     function initCloneByTag(object, tag, cloneFunc, isDeep) {
6218       var Ctor = object.constructor;
6219       switch (tag) {
6220         case arrayBufferTag:
6221           return cloneArrayBuffer(object);
6222
6223         case boolTag:
6224         case dateTag:
6225           return new Ctor(+object);
6226
6227         case dataViewTag:
6228           return cloneDataView(object, isDeep);
6229
6230         case float32Tag: case float64Tag:
6231         case int8Tag: case int16Tag: case int32Tag:
6232         case uint8Tag: case uint8ClampedTag: case uint16Tag: case uint32Tag:
6233           return cloneTypedArray(object, isDeep);
6234
6235         case mapTag:
6236           return cloneMap(object, isDeep, cloneFunc);
6237
6238         case numberTag:
6239         case stringTag:
6240           return new Ctor(object);
6241
6242         case regexpTag:
6243           return cloneRegExp(object);
6244
6245         case setTag:
6246           return cloneSet(object, isDeep, cloneFunc);
6247
6248         case symbolTag:
6249           return cloneSymbol(object);
6250       }
6251     }
6252
6253     /**
6254      * Inserts wrapper `details` in a comment at the top of the `source` body.
6255      *
6256      * @private
6257      * @param {string} source The source to modify.
6258      * @returns {Array} details The details to insert.
6259      * @returns {string} Returns the modified source.
6260      */
6261     function insertWrapDetails(source, details) {
6262       var length = details.length;
6263       if (!length) {
6264         return source;
6265       }
6266       var lastIndex = length - 1;
6267       details[lastIndex] = (length > 1 ? '& ' : '') + details[lastIndex];
6268       details = details.join(length > 2 ? ', ' : ' ');
6269       return source.replace(reWrapComment, '{\n/* [wrapped with ' + details + '] */\n');
6270     }
6271
6272     /**
6273      * Checks if `value` is a flattenable `arguments` object or array.
6274      *
6275      * @private
6276      * @param {*} value The value to check.
6277      * @returns {boolean} Returns `true` if `value` is flattenable, else `false`.
6278      */
6279     function isFlattenable(value) {
6280       return isArray(value) || isArguments(value) ||
6281         !!(spreadableSymbol && value && value[spreadableSymbol]);
6282     }
6283
6284     /**
6285      * Checks if `value` is a valid array-like index.
6286      *
6287      * @private
6288      * @param {*} value The value to check.
6289      * @param {number} [length=MAX_SAFE_INTEGER] The upper bounds of a valid index.
6290      * @returns {boolean} Returns `true` if `value` is a valid index, else `false`.
6291      */
6292     function isIndex(value, length) {
6293       length = length == null ? MAX_SAFE_INTEGER : length;
6294       return !!length &&
6295         (typeof value == 'number' || reIsUint.test(value)) &&
6296         (value > -1 && value % 1 == 0 && value < length);
6297     }
6298
6299     /**
6300      * Checks if the given arguments are from an iteratee call.
6301      *
6302      * @private
6303      * @param {*} value The potential iteratee value argument.
6304      * @param {*} index The potential iteratee index or key argument.
6305      * @param {*} object The potential iteratee object argument.
6306      * @returns {boolean} Returns `true` if the arguments are from an iteratee call,
6307      *  else `false`.
6308      */
6309     function isIterateeCall(value, index, object) {
6310       if (!isObject(object)) {
6311         return false;
6312       }
6313       var type = typeof index;
6314       if (type == 'number'
6315             ? (isArrayLike(object) && isIndex(index, object.length))
6316             : (type == 'string' && index in object)
6317           ) {
6318         return eq(object[index], value);
6319       }
6320       return false;
6321     }
6322
6323     /**
6324      * Checks if `value` is a property name and not a property path.
6325      *
6326      * @private
6327      * @param {*} value The value to check.
6328      * @param {Object} [object] The object to query keys on.
6329      * @returns {boolean} Returns `true` if `value` is a property name, else `false`.
6330      */
6331     function isKey(value, object) {
6332       if (isArray(value)) {
6333         return false;
6334       }
6335       var type = typeof value;
6336       if (type == 'number' || type == 'symbol' || type == 'boolean' ||
6337           value == null || isSymbol(value)) {
6338         return true;
6339       }
6340       return reIsPlainProp.test(value) || !reIsDeepProp.test(value) ||
6341         (object != null && value in Object(object));
6342     }
6343
6344     /**
6345      * Checks if `value` is suitable for use as unique object key.
6346      *
6347      * @private
6348      * @param {*} value The value to check.
6349      * @returns {boolean} Returns `true` if `value` is suitable, else `false`.
6350      */
6351     function isKeyable(value) {
6352       var type = typeof value;
6353       return (type == 'string' || type == 'number' || type == 'symbol' || type == 'boolean')
6354         ? (value !== '__proto__')
6355         : (value === null);
6356     }
6357
6358     /**
6359      * Checks if `func` has a lazy counterpart.
6360      *
6361      * @private
6362      * @param {Function} func The function to check.
6363      * @returns {boolean} Returns `true` if `func` has a lazy counterpart,
6364      *  else `false`.
6365      */
6366     function isLaziable(func) {
6367       var funcName = getFuncName(func),
6368           other = lodash[funcName];
6369
6370       if (typeof other != 'function' || !(funcName in LazyWrapper.prototype)) {
6371         return false;
6372       }
6373       if (func === other) {
6374         return true;
6375       }
6376       var data = getData(other);
6377       return !!data && func === data[0];
6378     }
6379
6380     /**
6381      * Checks if `func` has its source masked.
6382      *
6383      * @private
6384      * @param {Function} func The function to check.
6385      * @returns {boolean} Returns `true` if `func` is masked, else `false`.
6386      */
6387     function isMasked(func) {
6388       return !!maskSrcKey && (maskSrcKey in func);
6389     }
6390
6391     /**
6392      * Checks if `func` is capable of being masked.
6393      *
6394      * @private
6395      * @param {*} value The value to check.
6396      * @returns {boolean} Returns `true` if `func` is maskable, else `false`.
6397      */
6398     var isMaskable = coreJsData ? isFunction : stubFalse;
6399
6400     /**
6401      * Checks if `value` is likely a prototype object.
6402      *
6403      * @private
6404      * @param {*} value The value to check.
6405      * @returns {boolean} Returns `true` if `value` is a prototype, else `false`.
6406      */
6407     function isPrototype(value) {
6408       var Ctor = value && value.constructor,
6409           proto = (typeof Ctor == 'function' && Ctor.prototype) || objectProto;
6410
6411       return value === proto;
6412     }
6413
6414     /**
6415      * Checks if `value` is suitable for strict equality comparisons, i.e. `===`.
6416      *
6417      * @private
6418      * @param {*} value The value to check.
6419      * @returns {boolean} Returns `true` if `value` if suitable for strict
6420      *  equality comparisons, else `false`.
6421      */
6422     function isStrictComparable(value) {
6423       return value === value && !isObject(value);
6424     }
6425
6426     /**
6427      * A specialized version of `matchesProperty` for source values suitable
6428      * for strict equality comparisons, i.e. `===`.
6429      *
6430      * @private
6431      * @param {string} key The key of the property to get.
6432      * @param {*} srcValue The value to match.
6433      * @returns {Function} Returns the new spec function.
6434      */
6435     function matchesStrictComparable(key, srcValue) {
6436       return function(object) {
6437         if (object == null) {
6438           return false;
6439         }
6440         return object[key] === srcValue &&
6441           (srcValue !== undefined || (key in Object(object)));
6442       };
6443     }
6444
6445     /**
6446      * A specialized version of `_.memoize` which clears the memoized function's
6447      * cache when it exceeds `MAX_MEMOIZE_SIZE`.
6448      *
6449      * @private
6450      * @param {Function} func The function to have its output memoized.
6451      * @returns {Function} Returns the new memoized function.
6452      */
6453     function memoizeCapped(func) {
6454       var result = memoize(func, function(key) {
6455         if (cache.size === MAX_MEMOIZE_SIZE) {
6456           cache.clear();
6457         }
6458         return key;
6459       });
6460
6461       var cache = result.cache;
6462       return result;
6463     }
6464
6465     /**
6466      * Merges the function metadata of `source` into `data`.
6467      *
6468      * Merging metadata reduces the number of wrappers used to invoke a function.
6469      * This is possible because methods like `_.bind`, `_.curry`, and `_.partial`
6470      * may be applied regardless of execution order. Methods like `_.ary` and
6471      * `_.rearg` modify function arguments, making the order in which they are
6472      * executed important, preventing the merging of metadata. However, we make
6473      * an exception for a safe combined case where curried functions have `_.ary`
6474      * and or `_.rearg` applied.
6475      *
6476      * @private
6477      * @param {Array} data The destination metadata.
6478      * @param {Array} source The source metadata.
6479      * @returns {Array} Returns `data`.
6480      */
6481     function mergeData(data, source) {
6482       var bitmask = data[1],
6483           srcBitmask = source[1],
6484           newBitmask = bitmask | srcBitmask,
6485           isCommon = newBitmask < (WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG | WRAP_ARY_FLAG);
6486
6487       var isCombo =
6488         ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_CURRY_FLAG)) ||
6489         ((srcBitmask == WRAP_ARY_FLAG) && (bitmask == WRAP_REARG_FLAG) && (data[7].length <= source[8])) ||
6490         ((srcBitmask == (WRAP_ARY_FLAG | WRAP_REARG_FLAG)) && (source[7].length <= source[8]) && (bitmask == WRAP_CURRY_FLAG));
6491
6492       // Exit early if metadata can't be merged.
6493       if (!(isCommon || isCombo)) {
6494         return data;
6495       }
6496       // Use source `thisArg` if available.
6497       if (srcBitmask & WRAP_BIND_FLAG) {
6498         data[2] = source[2];
6499         // Set when currying a bound function.
6500         newBitmask |= bitmask & WRAP_BIND_FLAG ? 0 : WRAP_CURRY_BOUND_FLAG;
6501       }
6502       // Compose partial arguments.
6503       var value = source[3];
6504       if (value) {
6505         var partials = data[3];
6506         data[3] = partials ? composeArgs(partials, value, source[4]) : value;
6507         data[4] = partials ? replaceHolders(data[3], PLACEHOLDER) : source[4];
6508       }
6509       // Compose partial right arguments.
6510       value = source[5];
6511       if (value) {
6512         partials = data[5];
6513         data[5] = partials ? composeArgsRight(partials, value, source[6]) : value;
6514         data[6] = partials ? replaceHolders(data[5], PLACEHOLDER) : source[6];
6515       }
6516       // Use source `argPos` if available.
6517       value = source[7];
6518       if (value) {
6519         data[7] = value;
6520       }
6521       // Use source `ary` if it's smaller.
6522       if (srcBitmask & WRAP_ARY_FLAG) {
6523         data[8] = data[8] == null ? source[8] : nativeMin(data[8], source[8]);
6524       }
6525       // Use source `arity` if one is not provided.
6526       if (data[9] == null) {
6527         data[9] = source[9];
6528       }
6529       // Use source `func` and merge bitmasks.
6530       data[0] = source[0];
6531       data[1] = newBitmask;
6532
6533       return data;
6534     }
6535
6536     /**
6537      * Used by `_.defaultsDeep` to customize its `_.merge` use.
6538      *
6539      * @private
6540      * @param {*} objValue The destination value.
6541      * @param {*} srcValue The source value.
6542      * @param {string} key The key of the property to merge.
6543      * @param {Object} object The parent object of `objValue`.
6544      * @param {Object} source The parent object of `srcValue`.
6545      * @param {Object} [stack] Tracks traversed source values and their merged
6546      *  counterparts.
6547      * @returns {*} Returns the value to assign.
6548      */
6549     function mergeDefaults(objValue, srcValue, key, object, source, stack) {
6550       if (isObject(objValue) && isObject(srcValue)) {
6551         // Recursively merge objects and arrays (susceptible to call stack limits).
6552         stack.set(srcValue, objValue);
6553         baseMerge(objValue, srcValue, undefined, mergeDefaults, stack);
6554         stack['delete'](srcValue);
6555       }
6556       return objValue;
6557     }
6558
6559     /**
6560      * This function is like
6561      * [`Object.keys`](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
6562      * except that it includes inherited enumerable properties.
6563      *
6564      * @private
6565      * @param {Object} object The object to query.
6566      * @returns {Array} Returns the array of property names.
6567      */
6568     function nativeKeysIn(object) {
6569       var result = [];
6570       if (object != null) {
6571         for (var key in Object(object)) {
6572           result.push(key);
6573         }
6574       }
6575       return result;
6576     }
6577
6578     /**
6579      * Converts `value` to a string using `Object.prototype.toString`.
6580      *
6581      * @private
6582      * @param {*} value The value to convert.
6583      * @returns {string} Returns the converted string.
6584      */
6585     function objectToString(value) {
6586       return nativeObjectToString.call(value);
6587     }
6588
6589     /**
6590      * A specialized version of `baseRest` which transforms the rest array.
6591      *
6592      * @private
6593      * @param {Function} func The function to apply a rest parameter to.
6594      * @param {number} [start=func.length-1] The start position of the rest parameter.
6595      * @param {Function} transform The rest array transform.
6596      * @returns {Function} Returns the new function.
6597      */
6598     function overRest(func, start, transform) {
6599       start = nativeMax(start === undefined ? (func.length - 1) : start, 0);
6600       return function() {
6601         var args = arguments,
6602             index = -1,
6603             length = nativeMax(args.length - start, 0),
6604             array = Array(length);
6605
6606         while (++index < length) {
6607           array[index] = args[start + index];
6608         }
6609         index = -1;
6610         var otherArgs = Array(start + 1);
6611         while (++index < start) {
6612           otherArgs[index] = args[index];
6613         }
6614         otherArgs[start] = transform(array);
6615         return apply(func, this, otherArgs);
6616       };
6617     }
6618
6619     /**
6620      * Gets the parent value at `path` of `object`.
6621      *
6622      * @private
6623      * @param {Object} object The object to query.
6624      * @param {Array} path The path to get the parent value of.
6625      * @returns {*} Returns the parent value.
6626      */
6627     function parent(object, path) {
6628       return path.length == 1 ? object : baseGet(object, baseSlice(path, 0, -1));
6629     }
6630
6631     /**
6632      * Reorder `array` according to the specified indexes where the element at
6633      * the first index is assigned as the first element, the element at
6634      * the second index is assigned as the second element, and so on.
6635      *
6636      * @private
6637      * @param {Array} array The array to reorder.
6638      * @param {Array} indexes The arranged array indexes.
6639      * @returns {Array} Returns `array`.
6640      */
6641     function reorder(array, indexes) {
6642       var arrLength = array.length,
6643           length = nativeMin(indexes.length, arrLength),
6644           oldArray = copyArray(array);
6645
6646       while (length--) {
6647         var index = indexes[length];
6648         array[length] = isIndex(index, arrLength) ? oldArray[index] : undefined;
6649       }
6650       return array;
6651     }
6652
6653     /**
6654      * Sets metadata for `func`.
6655      *
6656      * **Note:** If this function becomes hot, i.e. is invoked a lot in a short
6657      * period of time, it will trip its breaker and transition to an identity
6658      * function to avoid garbage collection pauses in V8. See
6659      * [V8 issue 2070](https://bugs.chromium.org/p/v8/issues/detail?id=2070)
6660      * for more details.
6661      *
6662      * @private
6663      * @param {Function} func The function to associate metadata with.
6664      * @param {*} data The metadata.
6665      * @returns {Function} Returns `func`.
6666      */
6667     var setData = shortOut(baseSetData);
6668
6669     /**
6670      * A simple wrapper around the global [`setTimeout`](https://mdn.io/setTimeout).
6671      *
6672      * @private
6673      * @param {Function} func The function to delay.
6674      * @param {number} wait The number of milliseconds to delay invocation.
6675      * @returns {number|Object} Returns the timer id or timeout object.
6676      */
6677     var setTimeout = ctxSetTimeout || function(func, wait) {
6678       return root.setTimeout(func, wait);
6679     };
6680
6681     /**
6682      * Sets the `toString` method of `func` to return `string`.
6683      *
6684      * @private
6685      * @param {Function} func The function to modify.
6686      * @param {Function} string The `toString` result.
6687      * @returns {Function} Returns `func`.
6688      */
6689     var setToString = shortOut(baseSetToString);
6690
6691     /**
6692      * Sets the `toString` method of `wrapper` to mimic the source of `reference`
6693      * with wrapper details in a comment at the top of the source body.
6694      *
6695      * @private
6696      * @param {Function} wrapper The function to modify.
6697      * @param {Function} reference The reference function.
6698      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
6699      * @returns {Function} Returns `wrapper`.
6700      */
6701     function setWrapToString(wrapper, reference, bitmask) {
6702       var source = (reference + '');
6703       return setToString(wrapper, insertWrapDetails(source, updateWrapDetails(getWrapDetails(source), bitmask)));
6704     }
6705
6706     /**
6707      * Creates a function that'll short out and invoke `identity` instead
6708      * of `func` when it's called `HOT_COUNT` or more times in `HOT_SPAN`
6709      * milliseconds.
6710      *
6711      * @private
6712      * @param {Function} func The function to restrict.
6713      * @returns {Function} Returns the new shortable function.
6714      */
6715     function shortOut(func) {
6716       var count = 0,
6717           lastCalled = 0;
6718
6719       return function() {
6720         var stamp = nativeNow(),
6721             remaining = HOT_SPAN - (stamp - lastCalled);
6722
6723         lastCalled = stamp;
6724         if (remaining > 0) {
6725           if (++count >= HOT_COUNT) {
6726             return arguments[0];
6727           }
6728         } else {
6729           count = 0;
6730         }
6731         return func.apply(undefined, arguments);
6732       };
6733     }
6734
6735     /**
6736      * A specialized version of `_.shuffle` which mutates and sets the size of `array`.
6737      *
6738      * @private
6739      * @param {Array} array The array to shuffle.
6740      * @param {number} [size=array.length] The size of `array`.
6741      * @returns {Array} Returns `array`.
6742      */
6743     function shuffleSelf(array, size) {
6744       var index = -1,
6745           length = array.length,
6746           lastIndex = length - 1;
6747
6748       size = size === undefined ? length : size;
6749       while (++index < size) {
6750         var rand = baseRandom(index, lastIndex),
6751             value = array[rand];
6752
6753         array[rand] = array[index];
6754         array[index] = value;
6755       }
6756       array.length = size;
6757       return array;
6758     }
6759
6760     /**
6761      * Converts `string` to a property path array.
6762      *
6763      * @private
6764      * @param {string} string The string to convert.
6765      * @returns {Array} Returns the property path array.
6766      */
6767     var stringToPath = memoizeCapped(function(string) {
6768       string = toString(string);
6769
6770       var result = [];
6771       if (reLeadingDot.test(string)) {
6772         result.push('');
6773       }
6774       string.replace(rePropName, function(match, number, quote, string) {
6775         result.push(quote ? string.replace(reEscapeChar, '$1') : (number || match));
6776       });
6777       return result;
6778     });
6779
6780     /**
6781      * Converts `value` to a string key if it's not a string or symbol.
6782      *
6783      * @private
6784      * @param {*} value The value to inspect.
6785      * @returns {string|symbol} Returns the key.
6786      */
6787     function toKey(value) {
6788       if (typeof value == 'string' || isSymbol(value)) {
6789         return value;
6790       }
6791       var result = (value + '');
6792       return (result == '0' && (1 / value) == -INFINITY) ? '-0' : result;
6793     }
6794
6795     /**
6796      * Converts `func` to its source code.
6797      *
6798      * @private
6799      * @param {Function} func The function to convert.
6800      * @returns {string} Returns the source code.
6801      */
6802     function toSource(func) {
6803       if (func != null) {
6804         try {
6805           return funcToString.call(func);
6806         } catch (e) {}
6807         try {
6808           return (func + '');
6809         } catch (e) {}
6810       }
6811       return '';
6812     }
6813
6814     /**
6815      * Updates wrapper `details` based on `bitmask` flags.
6816      *
6817      * @private
6818      * @returns {Array} details The details to modify.
6819      * @param {number} bitmask The bitmask flags. See `createWrap` for more details.
6820      * @returns {Array} Returns `details`.
6821      */
6822     function updateWrapDetails(details, bitmask) {
6823       arrayEach(wrapFlags, function(pair) {
6824         var value = '_.' + pair[0];
6825         if ((bitmask & pair[1]) && !arrayIncludes(details, value)) {
6826           details.push(value);
6827         }
6828       });
6829       return details.sort();
6830     }
6831
6832     /**
6833      * Creates a clone of `wrapper`.
6834      *
6835      * @private
6836      * @param {Object} wrapper The wrapper to clone.
6837      * @returns {Object} Returns the cloned wrapper.
6838      */
6839     function wrapperClone(wrapper) {
6840       if (wrapper instanceof LazyWrapper) {
6841         return wrapper.clone();
6842       }
6843       var result = new LodashWrapper(wrapper.__wrapped__, wrapper.__chain__);
6844       result.__actions__ = copyArray(wrapper.__actions__);
6845       result.__index__  = wrapper.__index__;
6846       result.__values__ = wrapper.__values__;
6847       return result;
6848     }
6849
6850     /*------------------------------------------------------------------------*/
6851
6852     /**
6853      * Creates an array of elements split into groups the length of `size`.
6854      * If `array` can't be split evenly, the final chunk will be the remaining
6855      * elements.
6856      *
6857      * @static
6858      * @memberOf _
6859      * @since 3.0.0
6860      * @category Array
6861      * @param {Array} array The array to process.
6862      * @param {number} [size=1] The length of each chunk
6863      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
6864      * @returns {Array} Returns the new array of chunks.
6865      * @example
6866      *
6867      * _.chunk(['a', 'b', 'c', 'd'], 2);
6868      * // => [['a', 'b'], ['c', 'd']]
6869      *
6870      * _.chunk(['a', 'b', 'c', 'd'], 3);
6871      * // => [['a', 'b', 'c'], ['d']]
6872      */
6873     function chunk(array, size, guard) {
6874       if ((guard ? isIterateeCall(array, size, guard) : size === undefined)) {
6875         size = 1;
6876       } else {
6877         size = nativeMax(toInteger(size), 0);
6878       }
6879       var length = array == null ? 0 : array.length;
6880       if (!length || size < 1) {
6881         return [];
6882       }
6883       var index = 0,
6884           resIndex = 0,
6885           result = Array(nativeCeil(length / size));
6886
6887       while (index < length) {
6888         result[resIndex++] = baseSlice(array, index, (index += size));
6889       }
6890       return result;
6891     }
6892
6893     /**
6894      * Creates an array with all falsey values removed. The values `false`, `null`,
6895      * `0`, `""`, `undefined`, and `NaN` are falsey.
6896      *
6897      * @static
6898      * @memberOf _
6899      * @since 0.1.0
6900      * @category Array
6901      * @param {Array} array The array to compact.
6902      * @returns {Array} Returns the new array of filtered values.
6903      * @example
6904      *
6905      * _.compact([0, 1, false, 2, '', 3]);
6906      * // => [1, 2, 3]
6907      */
6908     function compact(array) {
6909       var index = -1,
6910           length = array == null ? 0 : array.length,
6911           resIndex = 0,
6912           result = [];
6913
6914       while (++index < length) {
6915         var value = array[index];
6916         if (value) {
6917           result[resIndex++] = value;
6918         }
6919       }
6920       return result;
6921     }
6922
6923     /**
6924      * Creates a new array concatenating `array` with any additional arrays
6925      * and/or values.
6926      *
6927      * @static
6928      * @memberOf _
6929      * @since 4.0.0
6930      * @category Array
6931      * @param {Array} array The array to concatenate.
6932      * @param {...*} [values] The values to concatenate.
6933      * @returns {Array} Returns the new concatenated array.
6934      * @example
6935      *
6936      * var array = [1];
6937      * var other = _.concat(array, 2, [3], [[4]]);
6938      *
6939      * console.log(other);
6940      * // => [1, 2, 3, [4]]
6941      *
6942      * console.log(array);
6943      * // => [1]
6944      */
6945     function concat() {
6946       var length = arguments.length;
6947       if (!length) {
6948         return [];
6949       }
6950       var args = Array(length - 1),
6951           array = arguments[0],
6952           index = length;
6953
6954       while (index--) {
6955         args[index - 1] = arguments[index];
6956       }
6957       return arrayPush(isArray(array) ? copyArray(array) : [array], baseFlatten(args, 1));
6958     }
6959
6960     /**
6961      * Creates an array of `array` values not included in the other given arrays
6962      * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
6963      * for equality comparisons. The order and references of result values are
6964      * determined by the first array.
6965      *
6966      * **Note:** Unlike `_.pullAll`, this method returns a new array.
6967      *
6968      * @static
6969      * @memberOf _
6970      * @since 0.1.0
6971      * @category Array
6972      * @param {Array} array The array to inspect.
6973      * @param {...Array} [values] The values to exclude.
6974      * @returns {Array} Returns the new array of filtered values.
6975      * @see _.without, _.xor
6976      * @example
6977      *
6978      * _.difference([2, 1], [2, 3]);
6979      * // => [1]
6980      */
6981     var difference = baseRest(function(array, values) {
6982       return isArrayLikeObject(array)
6983         ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true))
6984         : [];
6985     });
6986
6987     /**
6988      * This method is like `_.difference` except that it accepts `iteratee` which
6989      * is invoked for each element of `array` and `values` to generate the criterion
6990      * by which they're compared. The order and references of result values are
6991      * determined by the first array. The iteratee is invoked with one argument:
6992      * (value).
6993      *
6994      * **Note:** Unlike `_.pullAllBy`, this method returns a new array.
6995      *
6996      * @static
6997      * @memberOf _
6998      * @since 4.0.0
6999      * @category Array
7000      * @param {Array} array The array to inspect.
7001      * @param {...Array} [values] The values to exclude.
7002      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
7003      * @returns {Array} Returns the new array of filtered values.
7004      * @example
7005      *
7006      * _.differenceBy([2.1, 1.2], [2.3, 3.4], Math.floor);
7007      * // => [1.2]
7008      *
7009      * // The `_.property` iteratee shorthand.
7010      * _.differenceBy([{ 'x': 2 }, { 'x': 1 }], [{ 'x': 1 }], 'x');
7011      * // => [{ 'x': 2 }]
7012      */
7013     var differenceBy = baseRest(function(array, values) {
7014       var iteratee = last(values);
7015       if (isArrayLikeObject(iteratee)) {
7016         iteratee = undefined;
7017       }
7018       return isArrayLikeObject(array)
7019         ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), getIteratee(iteratee, 2))
7020         : [];
7021     });
7022
7023     /**
7024      * This method is like `_.difference` except that it accepts `comparator`
7025      * which is invoked to compare elements of `array` to `values`. The order and
7026      * references of result values are determined by the first array. The comparator
7027      * is invoked with two arguments: (arrVal, othVal).
7028      *
7029      * **Note:** Unlike `_.pullAllWith`, this method returns a new array.
7030      *
7031      * @static
7032      * @memberOf _
7033      * @since 4.0.0
7034      * @category Array
7035      * @param {Array} array The array to inspect.
7036      * @param {...Array} [values] The values to exclude.
7037      * @param {Function} [comparator] The comparator invoked per element.
7038      * @returns {Array} Returns the new array of filtered values.
7039      * @example
7040      *
7041      * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
7042      *
7043      * _.differenceWith(objects, [{ 'x': 1, 'y': 2 }], _.isEqual);
7044      * // => [{ 'x': 2, 'y': 1 }]
7045      */
7046     var differenceWith = baseRest(function(array, values) {
7047       var comparator = last(values);
7048       if (isArrayLikeObject(comparator)) {
7049         comparator = undefined;
7050       }
7051       return isArrayLikeObject(array)
7052         ? baseDifference(array, baseFlatten(values, 1, isArrayLikeObject, true), undefined, comparator)
7053         : [];
7054     });
7055
7056     /**
7057      * Creates a slice of `array` with `n` elements dropped from the beginning.
7058      *
7059      * @static
7060      * @memberOf _
7061      * @since 0.5.0
7062      * @category Array
7063      * @param {Array} array The array to query.
7064      * @param {number} [n=1] The number of elements to drop.
7065      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
7066      * @returns {Array} Returns the slice of `array`.
7067      * @example
7068      *
7069      * _.drop([1, 2, 3]);
7070      * // => [2, 3]
7071      *
7072      * _.drop([1, 2, 3], 2);
7073      * // => [3]
7074      *
7075      * _.drop([1, 2, 3], 5);
7076      * // => []
7077      *
7078      * _.drop([1, 2, 3], 0);
7079      * // => [1, 2, 3]
7080      */
7081     function drop(array, n, guard) {
7082       var length = array == null ? 0 : array.length;
7083       if (!length) {
7084         return [];
7085       }
7086       n = (guard || n === undefined) ? 1 : toInteger(n);
7087       return baseSlice(array, n < 0 ? 0 : n, length);
7088     }
7089
7090     /**
7091      * Creates a slice of `array` with `n` elements dropped from the end.
7092      *
7093      * @static
7094      * @memberOf _
7095      * @since 3.0.0
7096      * @category Array
7097      * @param {Array} array The array to query.
7098      * @param {number} [n=1] The number of elements to drop.
7099      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
7100      * @returns {Array} Returns the slice of `array`.
7101      * @example
7102      *
7103      * _.dropRight([1, 2, 3]);
7104      * // => [1, 2]
7105      *
7106      * _.dropRight([1, 2, 3], 2);
7107      * // => [1]
7108      *
7109      * _.dropRight([1, 2, 3], 5);
7110      * // => []
7111      *
7112      * _.dropRight([1, 2, 3], 0);
7113      * // => [1, 2, 3]
7114      */
7115     function dropRight(array, n, guard) {
7116       var length = array == null ? 0 : array.length;
7117       if (!length) {
7118         return [];
7119       }
7120       n = (guard || n === undefined) ? 1 : toInteger(n);
7121       n = length - n;
7122       return baseSlice(array, 0, n < 0 ? 0 : n);
7123     }
7124
7125     /**
7126      * Creates a slice of `array` excluding elements dropped from the end.
7127      * Elements are dropped until `predicate` returns falsey. The predicate is
7128      * invoked with three arguments: (value, index, array).
7129      *
7130      * @static
7131      * @memberOf _
7132      * @since 3.0.0
7133      * @category Array
7134      * @param {Array} array The array to query.
7135      * @param {Function} [predicate=_.identity] The function invoked per iteration.
7136      * @returns {Array} Returns the slice of `array`.
7137      * @example
7138      *
7139      * var users = [
7140      *   { 'user': 'barney',  'active': true },
7141      *   { 'user': 'fred',    'active': false },
7142      *   { 'user': 'pebbles', 'active': false }
7143      * ];
7144      *
7145      * _.dropRightWhile(users, function(o) { return !o.active; });
7146      * // => objects for ['barney']
7147      *
7148      * // The `_.matches` iteratee shorthand.
7149      * _.dropRightWhile(users, { 'user': 'pebbles', 'active': false });
7150      * // => objects for ['barney', 'fred']
7151      *
7152      * // The `_.matchesProperty` iteratee shorthand.
7153      * _.dropRightWhile(users, ['active', false]);
7154      * // => objects for ['barney']
7155      *
7156      * // The `_.property` iteratee shorthand.
7157      * _.dropRightWhile(users, 'active');
7158      * // => objects for ['barney', 'fred', 'pebbles']
7159      */
7160     function dropRightWhile(array, predicate) {
7161       return (array && array.length)
7162         ? baseWhile(array, getIteratee(predicate, 3), true, true)
7163         : [];
7164     }
7165
7166     /**
7167      * Creates a slice of `array` excluding elements dropped from the beginning.
7168      * Elements are dropped until `predicate` returns falsey. The predicate is
7169      * invoked with three arguments: (value, index, array).
7170      *
7171      * @static
7172      * @memberOf _
7173      * @since 3.0.0
7174      * @category Array
7175      * @param {Array} array The array to query.
7176      * @param {Function} [predicate=_.identity] The function invoked per iteration.
7177      * @returns {Array} Returns the slice of `array`.
7178      * @example
7179      *
7180      * var users = [
7181      *   { 'user': 'barney',  'active': false },
7182      *   { 'user': 'fred',    'active': false },
7183      *   { 'user': 'pebbles', 'active': true }
7184      * ];
7185      *
7186      * _.dropWhile(users, function(o) { return !o.active; });
7187      * // => objects for ['pebbles']
7188      *
7189      * // The `_.matches` iteratee shorthand.
7190      * _.dropWhile(users, { 'user': 'barney', 'active': false });
7191      * // => objects for ['fred', 'pebbles']
7192      *
7193      * // The `_.matchesProperty` iteratee shorthand.
7194      * _.dropWhile(users, ['active', false]);
7195      * // => objects for ['pebbles']
7196      *
7197      * // The `_.property` iteratee shorthand.
7198      * _.dropWhile(users, 'active');
7199      * // => objects for ['barney', 'fred', 'pebbles']
7200      */
7201     function dropWhile(array, predicate) {
7202       return (array && array.length)
7203         ? baseWhile(array, getIteratee(predicate, 3), true)
7204         : [];
7205     }
7206
7207     /**
7208      * Fills elements of `array` with `value` from `start` up to, but not
7209      * including, `end`.
7210      *
7211      * **Note:** This method mutates `array`.
7212      *
7213      * @static
7214      * @memberOf _
7215      * @since 3.2.0
7216      * @category Array
7217      * @param {Array} array The array to fill.
7218      * @param {*} value The value to fill `array` with.
7219      * @param {number} [start=0] The start position.
7220      * @param {number} [end=array.length] The end position.
7221      * @returns {Array} Returns `array`.
7222      * @example
7223      *
7224      * var array = [1, 2, 3];
7225      *
7226      * _.fill(array, 'a');
7227      * console.log(array);
7228      * // => ['a', 'a', 'a']
7229      *
7230      * _.fill(Array(3), 2);
7231      * // => [2, 2, 2]
7232      *
7233      * _.fill([4, 6, 8, 10], '*', 1, 3);
7234      * // => [4, '*', '*', 10]
7235      */
7236     function fill(array, value, start, end) {
7237       var length = array == null ? 0 : array.length;
7238       if (!length) {
7239         return [];
7240       }
7241       if (start && typeof start != 'number' && isIterateeCall(array, value, start)) {
7242         start = 0;
7243         end = length;
7244       }
7245       return baseFill(array, value, start, end);
7246     }
7247
7248     /**
7249      * This method is like `_.find` except that it returns the index of the first
7250      * element `predicate` returns truthy for instead of the element itself.
7251      *
7252      * @static
7253      * @memberOf _
7254      * @since 1.1.0
7255      * @category Array
7256      * @param {Array} array The array to inspect.
7257      * @param {Function} [predicate=_.identity] The function invoked per iteration.
7258      * @param {number} [fromIndex=0] The index to search from.
7259      * @returns {number} Returns the index of the found element, else `-1`.
7260      * @example
7261      *
7262      * var users = [
7263      *   { 'user': 'barney',  'active': false },
7264      *   { 'user': 'fred',    'active': false },
7265      *   { 'user': 'pebbles', 'active': true }
7266      * ];
7267      *
7268      * _.findIndex(users, function(o) { return o.user == 'barney'; });
7269      * // => 0
7270      *
7271      * // The `_.matches` iteratee shorthand.
7272      * _.findIndex(users, { 'user': 'fred', 'active': false });
7273      * // => 1
7274      *
7275      * // The `_.matchesProperty` iteratee shorthand.
7276      * _.findIndex(users, ['active', false]);
7277      * // => 0
7278      *
7279      * // The `_.property` iteratee shorthand.
7280      * _.findIndex(users, 'active');
7281      * // => 2
7282      */
7283     function findIndex(array, predicate, fromIndex) {
7284       var length = array == null ? 0 : array.length;
7285       if (!length) {
7286         return -1;
7287       }
7288       var index = fromIndex == null ? 0 : toInteger(fromIndex);
7289       if (index < 0) {
7290         index = nativeMax(length + index, 0);
7291       }
7292       return baseFindIndex(array, getIteratee(predicate, 3), index);
7293     }
7294
7295     /**
7296      * This method is like `_.findIndex` except that it iterates over elements
7297      * of `collection` from right to left.
7298      *
7299      * @static
7300      * @memberOf _
7301      * @since 2.0.0
7302      * @category Array
7303      * @param {Array} array The array to inspect.
7304      * @param {Function} [predicate=_.identity] The function invoked per iteration.
7305      * @param {number} [fromIndex=array.length-1] The index to search from.
7306      * @returns {number} Returns the index of the found element, else `-1`.
7307      * @example
7308      *
7309      * var users = [
7310      *   { 'user': 'barney',  'active': true },
7311      *   { 'user': 'fred',    'active': false },
7312      *   { 'user': 'pebbles', 'active': false }
7313      * ];
7314      *
7315      * _.findLastIndex(users, function(o) { return o.user == 'pebbles'; });
7316      * // => 2
7317      *
7318      * // The `_.matches` iteratee shorthand.
7319      * _.findLastIndex(users, { 'user': 'barney', 'active': true });
7320      * // => 0
7321      *
7322      * // The `_.matchesProperty` iteratee shorthand.
7323      * _.findLastIndex(users, ['active', false]);
7324      * // => 2
7325      *
7326      * // The `_.property` iteratee shorthand.
7327      * _.findLastIndex(users, 'active');
7328      * // => 0
7329      */
7330     function findLastIndex(array, predicate, fromIndex) {
7331       var length = array == null ? 0 : array.length;
7332       if (!length) {
7333         return -1;
7334       }
7335       var index = length - 1;
7336       if (fromIndex !== undefined) {
7337         index = toInteger(fromIndex);
7338         index = fromIndex < 0
7339           ? nativeMax(length + index, 0)
7340           : nativeMin(index, length - 1);
7341       }
7342       return baseFindIndex(array, getIteratee(predicate, 3), index, true);
7343     }
7344
7345     /**
7346      * Flattens `array` a single level deep.
7347      *
7348      * @static
7349      * @memberOf _
7350      * @since 0.1.0
7351      * @category Array
7352      * @param {Array} array The array to flatten.
7353      * @returns {Array} Returns the new flattened array.
7354      * @example
7355      *
7356      * _.flatten([1, [2, [3, [4]], 5]]);
7357      * // => [1, 2, [3, [4]], 5]
7358      */
7359     function flatten(array) {
7360       var length = array == null ? 0 : array.length;
7361       return length ? baseFlatten(array, 1) : [];
7362     }
7363
7364     /**
7365      * Recursively flattens `array`.
7366      *
7367      * @static
7368      * @memberOf _
7369      * @since 3.0.0
7370      * @category Array
7371      * @param {Array} array The array to flatten.
7372      * @returns {Array} Returns the new flattened array.
7373      * @example
7374      *
7375      * _.flattenDeep([1, [2, [3, [4]], 5]]);
7376      * // => [1, 2, 3, 4, 5]
7377      */
7378     function flattenDeep(array) {
7379       var length = array == null ? 0 : array.length;
7380       return length ? baseFlatten(array, INFINITY) : [];
7381     }
7382
7383     /**
7384      * Recursively flatten `array` up to `depth` times.
7385      *
7386      * @static
7387      * @memberOf _
7388      * @since 4.4.0
7389      * @category Array
7390      * @param {Array} array The array to flatten.
7391      * @param {number} [depth=1] The maximum recursion depth.
7392      * @returns {Array} Returns the new flattened array.
7393      * @example
7394      *
7395      * var array = [1, [2, [3, [4]], 5]];
7396      *
7397      * _.flattenDepth(array, 1);
7398      * // => [1, 2, [3, [4]], 5]
7399      *
7400      * _.flattenDepth(array, 2);
7401      * // => [1, 2, 3, [4], 5]
7402      */
7403     function flattenDepth(array, depth) {
7404       var length = array == null ? 0 : array.length;
7405       if (!length) {
7406         return [];
7407       }
7408       depth = depth === undefined ? 1 : toInteger(depth);
7409       return baseFlatten(array, depth);
7410     }
7411
7412     /**
7413      * The inverse of `_.toPairs`; this method returns an object composed
7414      * from key-value `pairs`.
7415      *
7416      * @static
7417      * @memberOf _
7418      * @since 4.0.0
7419      * @category Array
7420      * @param {Array} pairs The key-value pairs.
7421      * @returns {Object} Returns the new object.
7422      * @example
7423      *
7424      * _.fromPairs([['a', 1], ['b', 2]]);
7425      * // => { 'a': 1, 'b': 2 }
7426      */
7427     function fromPairs(pairs) {
7428       var index = -1,
7429           length = pairs == null ? 0 : pairs.length,
7430           result = {};
7431
7432       while (++index < length) {
7433         var pair = pairs[index];
7434         result[pair[0]] = pair[1];
7435       }
7436       return result;
7437     }
7438
7439     /**
7440      * Gets the first element of `array`.
7441      *
7442      * @static
7443      * @memberOf _
7444      * @since 0.1.0
7445      * @alias first
7446      * @category Array
7447      * @param {Array} array The array to query.
7448      * @returns {*} Returns the first element of `array`.
7449      * @example
7450      *
7451      * _.head([1, 2, 3]);
7452      * // => 1
7453      *
7454      * _.head([]);
7455      * // => undefined
7456      */
7457     function head(array) {
7458       return (array && array.length) ? array[0] : undefined;
7459     }
7460
7461     /**
7462      * Gets the index at which the first occurrence of `value` is found in `array`
7463      * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
7464      * for equality comparisons. If `fromIndex` is negative, it's used as the
7465      * offset from the end of `array`.
7466      *
7467      * @static
7468      * @memberOf _
7469      * @since 0.1.0
7470      * @category Array
7471      * @param {Array} array The array to inspect.
7472      * @param {*} value The value to search for.
7473      * @param {number} [fromIndex=0] The index to search from.
7474      * @returns {number} Returns the index of the matched value, else `-1`.
7475      * @example
7476      *
7477      * _.indexOf([1, 2, 1, 2], 2);
7478      * // => 1
7479      *
7480      * // Search from the `fromIndex`.
7481      * _.indexOf([1, 2, 1, 2], 2, 2);
7482      * // => 3
7483      */
7484     function indexOf(array, value, fromIndex) {
7485       var length = array == null ? 0 : array.length;
7486       if (!length) {
7487         return -1;
7488       }
7489       var index = fromIndex == null ? 0 : toInteger(fromIndex);
7490       if (index < 0) {
7491         index = nativeMax(length + index, 0);
7492       }
7493       return baseIndexOf(array, value, index);
7494     }
7495
7496     /**
7497      * Gets all but the last element of `array`.
7498      *
7499      * @static
7500      * @memberOf _
7501      * @since 0.1.0
7502      * @category Array
7503      * @param {Array} array The array to query.
7504      * @returns {Array} Returns the slice of `array`.
7505      * @example
7506      *
7507      * _.initial([1, 2, 3]);
7508      * // => [1, 2]
7509      */
7510     function initial(array) {
7511       var length = array == null ? 0 : array.length;
7512       return length ? baseSlice(array, 0, -1) : [];
7513     }
7514
7515     /**
7516      * Creates an array of unique values that are included in all given arrays
7517      * using [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
7518      * for equality comparisons. The order and references of result values are
7519      * determined by the first array.
7520      *
7521      * @static
7522      * @memberOf _
7523      * @since 0.1.0
7524      * @category Array
7525      * @param {...Array} [arrays] The arrays to inspect.
7526      * @returns {Array} Returns the new array of intersecting values.
7527      * @example
7528      *
7529      * _.intersection([2, 1], [2, 3]);
7530      * // => [2]
7531      */
7532     var intersection = baseRest(function(arrays) {
7533       var mapped = arrayMap(arrays, castArrayLikeObject);
7534       return (mapped.length && mapped[0] === arrays[0])
7535         ? baseIntersection(mapped)
7536         : [];
7537     });
7538
7539     /**
7540      * This method is like `_.intersection` except that it accepts `iteratee`
7541      * which is invoked for each element of each `arrays` to generate the criterion
7542      * by which they're compared. The order and references of result values are
7543      * determined by the first array. The iteratee is invoked with one argument:
7544      * (value).
7545      *
7546      * @static
7547      * @memberOf _
7548      * @since 4.0.0
7549      * @category Array
7550      * @param {...Array} [arrays] The arrays to inspect.
7551      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
7552      * @returns {Array} Returns the new array of intersecting values.
7553      * @example
7554      *
7555      * _.intersectionBy([2.1, 1.2], [2.3, 3.4], Math.floor);
7556      * // => [2.1]
7557      *
7558      * // The `_.property` iteratee shorthand.
7559      * _.intersectionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
7560      * // => [{ 'x': 1 }]
7561      */
7562     var intersectionBy = baseRest(function(arrays) {
7563       var iteratee = last(arrays),
7564           mapped = arrayMap(arrays, castArrayLikeObject);
7565
7566       if (iteratee === last(mapped)) {
7567         iteratee = undefined;
7568       } else {
7569         mapped.pop();
7570       }
7571       return (mapped.length && mapped[0] === arrays[0])
7572         ? baseIntersection(mapped, getIteratee(iteratee, 2))
7573         : [];
7574     });
7575
7576     /**
7577      * This method is like `_.intersection` except that it accepts `comparator`
7578      * which is invoked to compare elements of `arrays`. The order and references
7579      * of result values are determined by the first array. The comparator is
7580      * invoked with two arguments: (arrVal, othVal).
7581      *
7582      * @static
7583      * @memberOf _
7584      * @since 4.0.0
7585      * @category Array
7586      * @param {...Array} [arrays] The arrays to inspect.
7587      * @param {Function} [comparator] The comparator invoked per element.
7588      * @returns {Array} Returns the new array of intersecting values.
7589      * @example
7590      *
7591      * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
7592      * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
7593      *
7594      * _.intersectionWith(objects, others, _.isEqual);
7595      * // => [{ 'x': 1, 'y': 2 }]
7596      */
7597     var intersectionWith = baseRest(function(arrays) {
7598       var comparator = last(arrays),
7599           mapped = arrayMap(arrays, castArrayLikeObject);
7600
7601       comparator = typeof comparator == 'function' ? comparator : undefined;
7602       if (comparator) {
7603         mapped.pop();
7604       }
7605       return (mapped.length && mapped[0] === arrays[0])
7606         ? baseIntersection(mapped, undefined, comparator)
7607         : [];
7608     });
7609
7610     /**
7611      * Converts all elements in `array` into a string separated by `separator`.
7612      *
7613      * @static
7614      * @memberOf _
7615      * @since 4.0.0
7616      * @category Array
7617      * @param {Array} array The array to convert.
7618      * @param {string} [separator=','] The element separator.
7619      * @returns {string} Returns the joined string.
7620      * @example
7621      *
7622      * _.join(['a', 'b', 'c'], '~');
7623      * // => 'a~b~c'
7624      */
7625     function join(array, separator) {
7626       return array == null ? '' : nativeJoin.call(array, separator);
7627     }
7628
7629     /**
7630      * Gets the last element of `array`.
7631      *
7632      * @static
7633      * @memberOf _
7634      * @since 0.1.0
7635      * @category Array
7636      * @param {Array} array The array to query.
7637      * @returns {*} Returns the last element of `array`.
7638      * @example
7639      *
7640      * _.last([1, 2, 3]);
7641      * // => 3
7642      */
7643     function last(array) {
7644       var length = array == null ? 0 : array.length;
7645       return length ? array[length - 1] : undefined;
7646     }
7647
7648     /**
7649      * This method is like `_.indexOf` except that it iterates over elements of
7650      * `array` from right to left.
7651      *
7652      * @static
7653      * @memberOf _
7654      * @since 0.1.0
7655      * @category Array
7656      * @param {Array} array The array to inspect.
7657      * @param {*} value The value to search for.
7658      * @param {number} [fromIndex=array.length-1] The index to search from.
7659      * @returns {number} Returns the index of the matched value, else `-1`.
7660      * @example
7661      *
7662      * _.lastIndexOf([1, 2, 1, 2], 2);
7663      * // => 3
7664      *
7665      * // Search from the `fromIndex`.
7666      * _.lastIndexOf([1, 2, 1, 2], 2, 2);
7667      * // => 1
7668      */
7669     function lastIndexOf(array, value, fromIndex) {
7670       var length = array == null ? 0 : array.length;
7671       if (!length) {
7672         return -1;
7673       }
7674       var index = length;
7675       if (fromIndex !== undefined) {
7676         index = toInteger(fromIndex);
7677         index = index < 0 ? nativeMax(length + index, 0) : nativeMin(index, length - 1);
7678       }
7679       return value === value
7680         ? strictLastIndexOf(array, value, index)
7681         : baseFindIndex(array, baseIsNaN, index, true);
7682     }
7683
7684     /**
7685      * Gets the element at index `n` of `array`. If `n` is negative, the nth
7686      * element from the end is returned.
7687      *
7688      * @static
7689      * @memberOf _
7690      * @since 4.11.0
7691      * @category Array
7692      * @param {Array} array The array to query.
7693      * @param {number} [n=0] The index of the element to return.
7694      * @returns {*} Returns the nth element of `array`.
7695      * @example
7696      *
7697      * var array = ['a', 'b', 'c', 'd'];
7698      *
7699      * _.nth(array, 1);
7700      * // => 'b'
7701      *
7702      * _.nth(array, -2);
7703      * // => 'c';
7704      */
7705     function nth(array, n) {
7706       return (array && array.length) ? baseNth(array, toInteger(n)) : undefined;
7707     }
7708
7709     /**
7710      * Removes all given values from `array` using
7711      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
7712      * for equality comparisons.
7713      *
7714      * **Note:** Unlike `_.without`, this method mutates `array`. Use `_.remove`
7715      * to remove elements from an array by predicate.
7716      *
7717      * @static
7718      * @memberOf _
7719      * @since 2.0.0
7720      * @category Array
7721      * @param {Array} array The array to modify.
7722      * @param {...*} [values] The values to remove.
7723      * @returns {Array} Returns `array`.
7724      * @example
7725      *
7726      * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
7727      *
7728      * _.pull(array, 'a', 'c');
7729      * console.log(array);
7730      * // => ['b', 'b']
7731      */
7732     var pull = baseRest(pullAll);
7733
7734     /**
7735      * This method is like `_.pull` except that it accepts an array of values to remove.
7736      *
7737      * **Note:** Unlike `_.difference`, this method mutates `array`.
7738      *
7739      * @static
7740      * @memberOf _
7741      * @since 4.0.0
7742      * @category Array
7743      * @param {Array} array The array to modify.
7744      * @param {Array} values The values to remove.
7745      * @returns {Array} Returns `array`.
7746      * @example
7747      *
7748      * var array = ['a', 'b', 'c', 'a', 'b', 'c'];
7749      *
7750      * _.pullAll(array, ['a', 'c']);
7751      * console.log(array);
7752      * // => ['b', 'b']
7753      */
7754     function pullAll(array, values) {
7755       return (array && array.length && values && values.length)
7756         ? basePullAll(array, values)
7757         : array;
7758     }
7759
7760     /**
7761      * This method is like `_.pullAll` except that it accepts `iteratee` which is
7762      * invoked for each element of `array` and `values` to generate the criterion
7763      * by which they're compared. The iteratee is invoked with one argument: (value).
7764      *
7765      * **Note:** Unlike `_.differenceBy`, this method mutates `array`.
7766      *
7767      * @static
7768      * @memberOf _
7769      * @since 4.0.0
7770      * @category Array
7771      * @param {Array} array The array to modify.
7772      * @param {Array} values The values to remove.
7773      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
7774      * @returns {Array} Returns `array`.
7775      * @example
7776      *
7777      * var array = [{ 'x': 1 }, { 'x': 2 }, { 'x': 3 }, { 'x': 1 }];
7778      *
7779      * _.pullAllBy(array, [{ 'x': 1 }, { 'x': 3 }], 'x');
7780      * console.log(array);
7781      * // => [{ 'x': 2 }]
7782      */
7783     function pullAllBy(array, values, iteratee) {
7784       return (array && array.length && values && values.length)
7785         ? basePullAll(array, values, getIteratee(iteratee, 2))
7786         : array;
7787     }
7788
7789     /**
7790      * This method is like `_.pullAll` except that it accepts `comparator` which
7791      * is invoked to compare elements of `array` to `values`. The comparator is
7792      * invoked with two arguments: (arrVal, othVal).
7793      *
7794      * **Note:** Unlike `_.differenceWith`, this method mutates `array`.
7795      *
7796      * @static
7797      * @memberOf _
7798      * @since 4.6.0
7799      * @category Array
7800      * @param {Array} array The array to modify.
7801      * @param {Array} values The values to remove.
7802      * @param {Function} [comparator] The comparator invoked per element.
7803      * @returns {Array} Returns `array`.
7804      * @example
7805      *
7806      * var array = [{ 'x': 1, 'y': 2 }, { 'x': 3, 'y': 4 }, { 'x': 5, 'y': 6 }];
7807      *
7808      * _.pullAllWith(array, [{ 'x': 3, 'y': 4 }], _.isEqual);
7809      * console.log(array);
7810      * // => [{ 'x': 1, 'y': 2 }, { 'x': 5, 'y': 6 }]
7811      */
7812     function pullAllWith(array, values, comparator) {
7813       return (array && array.length && values && values.length)
7814         ? basePullAll(array, values, undefined, comparator)
7815         : array;
7816     }
7817
7818     /**
7819      * Removes elements from `array` corresponding to `indexes` and returns an
7820      * array of removed elements.
7821      *
7822      * **Note:** Unlike `_.at`, this method mutates `array`.
7823      *
7824      * @static
7825      * @memberOf _
7826      * @since 3.0.0
7827      * @category Array
7828      * @param {Array} array The array to modify.
7829      * @param {...(number|number[])} [indexes] The indexes of elements to remove.
7830      * @returns {Array} Returns the new array of removed elements.
7831      * @example
7832      *
7833      * var array = ['a', 'b', 'c', 'd'];
7834      * var pulled = _.pullAt(array, [1, 3]);
7835      *
7836      * console.log(array);
7837      * // => ['a', 'c']
7838      *
7839      * console.log(pulled);
7840      * // => ['b', 'd']
7841      */
7842     var pullAt = flatRest(function(array, indexes) {
7843       var length = array == null ? 0 : array.length,
7844           result = baseAt(array, indexes);
7845
7846       basePullAt(array, arrayMap(indexes, function(index) {
7847         return isIndex(index, length) ? +index : index;
7848       }).sort(compareAscending));
7849
7850       return result;
7851     });
7852
7853     /**
7854      * Removes all elements from `array` that `predicate` returns truthy for
7855      * and returns an array of the removed elements. The predicate is invoked
7856      * with three arguments: (value, index, array).
7857      *
7858      * **Note:** Unlike `_.filter`, this method mutates `array`. Use `_.pull`
7859      * to pull elements from an array by value.
7860      *
7861      * @static
7862      * @memberOf _
7863      * @since 2.0.0
7864      * @category Array
7865      * @param {Array} array The array to modify.
7866      * @param {Function} [predicate=_.identity] The function invoked per iteration.
7867      * @returns {Array} Returns the new array of removed elements.
7868      * @example
7869      *
7870      * var array = [1, 2, 3, 4];
7871      * var evens = _.remove(array, function(n) {
7872      *   return n % 2 == 0;
7873      * });
7874      *
7875      * console.log(array);
7876      * // => [1, 3]
7877      *
7878      * console.log(evens);
7879      * // => [2, 4]
7880      */
7881     function remove(array, predicate) {
7882       var result = [];
7883       if (!(array && array.length)) {
7884         return result;
7885       }
7886       var index = -1,
7887           indexes = [],
7888           length = array.length;
7889
7890       predicate = getIteratee(predicate, 3);
7891       while (++index < length) {
7892         var value = array[index];
7893         if (predicate(value, index, array)) {
7894           result.push(value);
7895           indexes.push(index);
7896         }
7897       }
7898       basePullAt(array, indexes);
7899       return result;
7900     }
7901
7902     /**
7903      * Reverses `array` so that the first element becomes the last, the second
7904      * element becomes the second to last, and so on.
7905      *
7906      * **Note:** This method mutates `array` and is based on
7907      * [`Array#reverse`](https://mdn.io/Array/reverse).
7908      *
7909      * @static
7910      * @memberOf _
7911      * @since 4.0.0
7912      * @category Array
7913      * @param {Array} array The array to modify.
7914      * @returns {Array} Returns `array`.
7915      * @example
7916      *
7917      * var array = [1, 2, 3];
7918      *
7919      * _.reverse(array);
7920      * // => [3, 2, 1]
7921      *
7922      * console.log(array);
7923      * // => [3, 2, 1]
7924      */
7925     function reverse(array) {
7926       return array == null ? array : nativeReverse.call(array);
7927     }
7928
7929     /**
7930      * Creates a slice of `array` from `start` up to, but not including, `end`.
7931      *
7932      * **Note:** This method is used instead of
7933      * [`Array#slice`](https://mdn.io/Array/slice) to ensure dense arrays are
7934      * returned.
7935      *
7936      * @static
7937      * @memberOf _
7938      * @since 3.0.0
7939      * @category Array
7940      * @param {Array} array The array to slice.
7941      * @param {number} [start=0] The start position.
7942      * @param {number} [end=array.length] The end position.
7943      * @returns {Array} Returns the slice of `array`.
7944      */
7945     function slice(array, start, end) {
7946       var length = array == null ? 0 : array.length;
7947       if (!length) {
7948         return [];
7949       }
7950       if (end && typeof end != 'number' && isIterateeCall(array, start, end)) {
7951         start = 0;
7952         end = length;
7953       }
7954       else {
7955         start = start == null ? 0 : toInteger(start);
7956         end = end === undefined ? length : toInteger(end);
7957       }
7958       return baseSlice(array, start, end);
7959     }
7960
7961     /**
7962      * Uses a binary search to determine the lowest index at which `value`
7963      * should be inserted into `array` in order to maintain its sort order.
7964      *
7965      * @static
7966      * @memberOf _
7967      * @since 0.1.0
7968      * @category Array
7969      * @param {Array} array The sorted array to inspect.
7970      * @param {*} value The value to evaluate.
7971      * @returns {number} Returns the index at which `value` should be inserted
7972      *  into `array`.
7973      * @example
7974      *
7975      * _.sortedIndex([30, 50], 40);
7976      * // => 1
7977      */
7978     function sortedIndex(array, value) {
7979       return baseSortedIndex(array, value);
7980     }
7981
7982     /**
7983      * This method is like `_.sortedIndex` except that it accepts `iteratee`
7984      * which is invoked for `value` and each element of `array` to compute their
7985      * sort ranking. The iteratee is invoked with one argument: (value).
7986      *
7987      * @static
7988      * @memberOf _
7989      * @since 4.0.0
7990      * @category Array
7991      * @param {Array} array The sorted array to inspect.
7992      * @param {*} value The value to evaluate.
7993      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
7994      * @returns {number} Returns the index at which `value` should be inserted
7995      *  into `array`.
7996      * @example
7997      *
7998      * var objects = [{ 'x': 4 }, { 'x': 5 }];
7999      *
8000      * _.sortedIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
8001      * // => 0
8002      *
8003      * // The `_.property` iteratee shorthand.
8004      * _.sortedIndexBy(objects, { 'x': 4 }, 'x');
8005      * // => 0
8006      */
8007     function sortedIndexBy(array, value, iteratee) {
8008       return baseSortedIndexBy(array, value, getIteratee(iteratee, 2));
8009     }
8010
8011     /**
8012      * This method is like `_.indexOf` except that it performs a binary
8013      * search on a sorted `array`.
8014      *
8015      * @static
8016      * @memberOf _
8017      * @since 4.0.0
8018      * @category Array
8019      * @param {Array} array The array to inspect.
8020      * @param {*} value The value to search for.
8021      * @returns {number} Returns the index of the matched value, else `-1`.
8022      * @example
8023      *
8024      * _.sortedIndexOf([4, 5, 5, 5, 6], 5);
8025      * // => 1
8026      */
8027     function sortedIndexOf(array, value) {
8028       var length = array == null ? 0 : array.length;
8029       if (length) {
8030         var index = baseSortedIndex(array, value);
8031         if (index < length && eq(array[index], value)) {
8032           return index;
8033         }
8034       }
8035       return -1;
8036     }
8037
8038     /**
8039      * This method is like `_.sortedIndex` except that it returns the highest
8040      * index at which `value` should be inserted into `array` in order to
8041      * maintain its sort order.
8042      *
8043      * @static
8044      * @memberOf _
8045      * @since 3.0.0
8046      * @category Array
8047      * @param {Array} array The sorted array to inspect.
8048      * @param {*} value The value to evaluate.
8049      * @returns {number} Returns the index at which `value` should be inserted
8050      *  into `array`.
8051      * @example
8052      *
8053      * _.sortedLastIndex([4, 5, 5, 5, 6], 5);
8054      * // => 4
8055      */
8056     function sortedLastIndex(array, value) {
8057       return baseSortedIndex(array, value, true);
8058     }
8059
8060     /**
8061      * This method is like `_.sortedLastIndex` except that it accepts `iteratee`
8062      * which is invoked for `value` and each element of `array` to compute their
8063      * sort ranking. The iteratee is invoked with one argument: (value).
8064      *
8065      * @static
8066      * @memberOf _
8067      * @since 4.0.0
8068      * @category Array
8069      * @param {Array} array The sorted array to inspect.
8070      * @param {*} value The value to evaluate.
8071      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8072      * @returns {number} Returns the index at which `value` should be inserted
8073      *  into `array`.
8074      * @example
8075      *
8076      * var objects = [{ 'x': 4 }, { 'x': 5 }];
8077      *
8078      * _.sortedLastIndexBy(objects, { 'x': 4 }, function(o) { return o.x; });
8079      * // => 1
8080      *
8081      * // The `_.property` iteratee shorthand.
8082      * _.sortedLastIndexBy(objects, { 'x': 4 }, 'x');
8083      * // => 1
8084      */
8085     function sortedLastIndexBy(array, value, iteratee) {
8086       return baseSortedIndexBy(array, value, getIteratee(iteratee, 2), true);
8087     }
8088
8089     /**
8090      * This method is like `_.lastIndexOf` except that it performs a binary
8091      * search on a sorted `array`.
8092      *
8093      * @static
8094      * @memberOf _
8095      * @since 4.0.0
8096      * @category Array
8097      * @param {Array} array The array to inspect.
8098      * @param {*} value The value to search for.
8099      * @returns {number} Returns the index of the matched value, else `-1`.
8100      * @example
8101      *
8102      * _.sortedLastIndexOf([4, 5, 5, 5, 6], 5);
8103      * // => 3
8104      */
8105     function sortedLastIndexOf(array, value) {
8106       var length = array == null ? 0 : array.length;
8107       if (length) {
8108         var index = baseSortedIndex(array, value, true) - 1;
8109         if (eq(array[index], value)) {
8110           return index;
8111         }
8112       }
8113       return -1;
8114     }
8115
8116     /**
8117      * This method is like `_.uniq` except that it's designed and optimized
8118      * for sorted arrays.
8119      *
8120      * @static
8121      * @memberOf _
8122      * @since 4.0.0
8123      * @category Array
8124      * @param {Array} array The array to inspect.
8125      * @returns {Array} Returns the new duplicate free array.
8126      * @example
8127      *
8128      * _.sortedUniq([1, 1, 2]);
8129      * // => [1, 2]
8130      */
8131     function sortedUniq(array) {
8132       return (array && array.length)
8133         ? baseSortedUniq(array)
8134         : [];
8135     }
8136
8137     /**
8138      * This method is like `_.uniqBy` except that it's designed and optimized
8139      * for sorted arrays.
8140      *
8141      * @static
8142      * @memberOf _
8143      * @since 4.0.0
8144      * @category Array
8145      * @param {Array} array The array to inspect.
8146      * @param {Function} [iteratee] The iteratee invoked per element.
8147      * @returns {Array} Returns the new duplicate free array.
8148      * @example
8149      *
8150      * _.sortedUniqBy([1.1, 1.2, 2.3, 2.4], Math.floor);
8151      * // => [1.1, 2.3]
8152      */
8153     function sortedUniqBy(array, iteratee) {
8154       return (array && array.length)
8155         ? baseSortedUniq(array, getIteratee(iteratee, 2))
8156         : [];
8157     }
8158
8159     /**
8160      * Gets all but the first element of `array`.
8161      *
8162      * @static
8163      * @memberOf _
8164      * @since 4.0.0
8165      * @category Array
8166      * @param {Array} array The array to query.
8167      * @returns {Array} Returns the slice of `array`.
8168      * @example
8169      *
8170      * _.tail([1, 2, 3]);
8171      * // => [2, 3]
8172      */
8173     function tail(array) {
8174       var length = array == null ? 0 : array.length;
8175       return length ? baseSlice(array, 1, length) : [];
8176     }
8177
8178     /**
8179      * Creates a slice of `array` with `n` elements taken from the beginning.
8180      *
8181      * @static
8182      * @memberOf _
8183      * @since 0.1.0
8184      * @category Array
8185      * @param {Array} array The array to query.
8186      * @param {number} [n=1] The number of elements to take.
8187      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
8188      * @returns {Array} Returns the slice of `array`.
8189      * @example
8190      *
8191      * _.take([1, 2, 3]);
8192      * // => [1]
8193      *
8194      * _.take([1, 2, 3], 2);
8195      * // => [1, 2]
8196      *
8197      * _.take([1, 2, 3], 5);
8198      * // => [1, 2, 3]
8199      *
8200      * _.take([1, 2, 3], 0);
8201      * // => []
8202      */
8203     function take(array, n, guard) {
8204       if (!(array && array.length)) {
8205         return [];
8206       }
8207       n = (guard || n === undefined) ? 1 : toInteger(n);
8208       return baseSlice(array, 0, n < 0 ? 0 : n);
8209     }
8210
8211     /**
8212      * Creates a slice of `array` with `n` elements taken from the end.
8213      *
8214      * @static
8215      * @memberOf _
8216      * @since 3.0.0
8217      * @category Array
8218      * @param {Array} array The array to query.
8219      * @param {number} [n=1] The number of elements to take.
8220      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
8221      * @returns {Array} Returns the slice of `array`.
8222      * @example
8223      *
8224      * _.takeRight([1, 2, 3]);
8225      * // => [3]
8226      *
8227      * _.takeRight([1, 2, 3], 2);
8228      * // => [2, 3]
8229      *
8230      * _.takeRight([1, 2, 3], 5);
8231      * // => [1, 2, 3]
8232      *
8233      * _.takeRight([1, 2, 3], 0);
8234      * // => []
8235      */
8236     function takeRight(array, n, guard) {
8237       var length = array == null ? 0 : array.length;
8238       if (!length) {
8239         return [];
8240       }
8241       n = (guard || n === undefined) ? 1 : toInteger(n);
8242       n = length - n;
8243       return baseSlice(array, n < 0 ? 0 : n, length);
8244     }
8245
8246     /**
8247      * Creates a slice of `array` with elements taken from the end. Elements are
8248      * taken until `predicate` returns falsey. The predicate is invoked with
8249      * three arguments: (value, index, array).
8250      *
8251      * @static
8252      * @memberOf _
8253      * @since 3.0.0
8254      * @category Array
8255      * @param {Array} array The array to query.
8256      * @param {Function} [predicate=_.identity] The function invoked per iteration.
8257      * @returns {Array} Returns the slice of `array`.
8258      * @example
8259      *
8260      * var users = [
8261      *   { 'user': 'barney',  'active': true },
8262      *   { 'user': 'fred',    'active': false },
8263      *   { 'user': 'pebbles', 'active': false }
8264      * ];
8265      *
8266      * _.takeRightWhile(users, function(o) { return !o.active; });
8267      * // => objects for ['fred', 'pebbles']
8268      *
8269      * // The `_.matches` iteratee shorthand.
8270      * _.takeRightWhile(users, { 'user': 'pebbles', 'active': false });
8271      * // => objects for ['pebbles']
8272      *
8273      * // The `_.matchesProperty` iteratee shorthand.
8274      * _.takeRightWhile(users, ['active', false]);
8275      * // => objects for ['fred', 'pebbles']
8276      *
8277      * // The `_.property` iteratee shorthand.
8278      * _.takeRightWhile(users, 'active');
8279      * // => []
8280      */
8281     function takeRightWhile(array, predicate) {
8282       return (array && array.length)
8283         ? baseWhile(array, getIteratee(predicate, 3), false, true)
8284         : [];
8285     }
8286
8287     /**
8288      * Creates a slice of `array` with elements taken from the beginning. Elements
8289      * are taken until `predicate` returns falsey. The predicate is invoked with
8290      * three arguments: (value, index, array).
8291      *
8292      * @static
8293      * @memberOf _
8294      * @since 3.0.0
8295      * @category Array
8296      * @param {Array} array The array to query.
8297      * @param {Function} [predicate=_.identity] The function invoked per iteration.
8298      * @returns {Array} Returns the slice of `array`.
8299      * @example
8300      *
8301      * var users = [
8302      *   { 'user': 'barney',  'active': false },
8303      *   { 'user': 'fred',    'active': false},
8304      *   { 'user': 'pebbles', 'active': true }
8305      * ];
8306      *
8307      * _.takeWhile(users, function(o) { return !o.active; });
8308      * // => objects for ['barney', 'fred']
8309      *
8310      * // The `_.matches` iteratee shorthand.
8311      * _.takeWhile(users, { 'user': 'barney', 'active': false });
8312      * // => objects for ['barney']
8313      *
8314      * // The `_.matchesProperty` iteratee shorthand.
8315      * _.takeWhile(users, ['active', false]);
8316      * // => objects for ['barney', 'fred']
8317      *
8318      * // The `_.property` iteratee shorthand.
8319      * _.takeWhile(users, 'active');
8320      * // => []
8321      */
8322     function takeWhile(array, predicate) {
8323       return (array && array.length)
8324         ? baseWhile(array, getIteratee(predicate, 3))
8325         : [];
8326     }
8327
8328     /**
8329      * Creates an array of unique values, in order, from all given arrays using
8330      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
8331      * for equality comparisons.
8332      *
8333      * @static
8334      * @memberOf _
8335      * @since 0.1.0
8336      * @category Array
8337      * @param {...Array} [arrays] The arrays to inspect.
8338      * @returns {Array} Returns the new array of combined values.
8339      * @example
8340      *
8341      * _.union([2], [1, 2]);
8342      * // => [2, 1]
8343      */
8344     var union = baseRest(function(arrays) {
8345       return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true));
8346     });
8347
8348     /**
8349      * This method is like `_.union` except that it accepts `iteratee` which is
8350      * invoked for each element of each `arrays` to generate the criterion by
8351      * which uniqueness is computed. Result values are chosen from the first
8352      * array in which the value occurs. The iteratee is invoked with one argument:
8353      * (value).
8354      *
8355      * @static
8356      * @memberOf _
8357      * @since 4.0.0
8358      * @category Array
8359      * @param {...Array} [arrays] The arrays to inspect.
8360      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8361      * @returns {Array} Returns the new array of combined values.
8362      * @example
8363      *
8364      * _.unionBy([2.1], [1.2, 2.3], Math.floor);
8365      * // => [2.1, 1.2]
8366      *
8367      * // The `_.property` iteratee shorthand.
8368      * _.unionBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
8369      * // => [{ 'x': 1 }, { 'x': 2 }]
8370      */
8371     var unionBy = baseRest(function(arrays) {
8372       var iteratee = last(arrays);
8373       if (isArrayLikeObject(iteratee)) {
8374         iteratee = undefined;
8375       }
8376       return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), getIteratee(iteratee, 2));
8377     });
8378
8379     /**
8380      * This method is like `_.union` except that it accepts `comparator` which
8381      * is invoked to compare elements of `arrays`. Result values are chosen from
8382      * the first array in which the value occurs. The comparator is invoked
8383      * with two arguments: (arrVal, othVal).
8384      *
8385      * @static
8386      * @memberOf _
8387      * @since 4.0.0
8388      * @category Array
8389      * @param {...Array} [arrays] The arrays to inspect.
8390      * @param {Function} [comparator] The comparator invoked per element.
8391      * @returns {Array} Returns the new array of combined values.
8392      * @example
8393      *
8394      * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
8395      * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
8396      *
8397      * _.unionWith(objects, others, _.isEqual);
8398      * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
8399      */
8400     var unionWith = baseRest(function(arrays) {
8401       var comparator = last(arrays);
8402       comparator = typeof comparator == 'function' ? comparator : undefined;
8403       return baseUniq(baseFlatten(arrays, 1, isArrayLikeObject, true), undefined, comparator);
8404     });
8405
8406     /**
8407      * Creates a duplicate-free version of an array, using
8408      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
8409      * for equality comparisons, in which only the first occurrence of each element
8410      * is kept. The order of result values is determined by the order they occur
8411      * in the array.
8412      *
8413      * @static
8414      * @memberOf _
8415      * @since 0.1.0
8416      * @category Array
8417      * @param {Array} array The array to inspect.
8418      * @returns {Array} Returns the new duplicate free array.
8419      * @example
8420      *
8421      * _.uniq([2, 1, 2]);
8422      * // => [2, 1]
8423      */
8424     function uniq(array) {
8425       return (array && array.length) ? baseUniq(array) : [];
8426     }
8427
8428     /**
8429      * This method is like `_.uniq` except that it accepts `iteratee` which is
8430      * invoked for each element in `array` to generate the criterion by which
8431      * uniqueness is computed. The order of result values is determined by the
8432      * order they occur in the array. The iteratee is invoked with one argument:
8433      * (value).
8434      *
8435      * @static
8436      * @memberOf _
8437      * @since 4.0.0
8438      * @category Array
8439      * @param {Array} array The array to inspect.
8440      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8441      * @returns {Array} Returns the new duplicate free array.
8442      * @example
8443      *
8444      * _.uniqBy([2.1, 1.2, 2.3], Math.floor);
8445      * // => [2.1, 1.2]
8446      *
8447      * // The `_.property` iteratee shorthand.
8448      * _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
8449      * // => [{ 'x': 1 }, { 'x': 2 }]
8450      */
8451     function uniqBy(array, iteratee) {
8452       return (array && array.length) ? baseUniq(array, getIteratee(iteratee, 2)) : [];
8453     }
8454
8455     /**
8456      * This method is like `_.uniq` except that it accepts `comparator` which
8457      * is invoked to compare elements of `array`. The order of result values is
8458      * determined by the order they occur in the array.The comparator is invoked
8459      * with two arguments: (arrVal, othVal).
8460      *
8461      * @static
8462      * @memberOf _
8463      * @since 4.0.0
8464      * @category Array
8465      * @param {Array} array The array to inspect.
8466      * @param {Function} [comparator] The comparator invoked per element.
8467      * @returns {Array} Returns the new duplicate free array.
8468      * @example
8469      *
8470      * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
8471      *
8472      * _.uniqWith(objects, _.isEqual);
8473      * // => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]
8474      */
8475     function uniqWith(array, comparator) {
8476       comparator = typeof comparator == 'function' ? comparator : undefined;
8477       return (array && array.length) ? baseUniq(array, undefined, comparator) : [];
8478     }
8479
8480     /**
8481      * This method is like `_.zip` except that it accepts an array of grouped
8482      * elements and creates an array regrouping the elements to their pre-zip
8483      * configuration.
8484      *
8485      * @static
8486      * @memberOf _
8487      * @since 1.2.0
8488      * @category Array
8489      * @param {Array} array The array of grouped elements to process.
8490      * @returns {Array} Returns the new array of regrouped elements.
8491      * @example
8492      *
8493      * var zipped = _.zip(['a', 'b'], [1, 2], [true, false]);
8494      * // => [['a', 1, true], ['b', 2, false]]
8495      *
8496      * _.unzip(zipped);
8497      * // => [['a', 'b'], [1, 2], [true, false]]
8498      */
8499     function unzip(array) {
8500       if (!(array && array.length)) {
8501         return [];
8502       }
8503       var length = 0;
8504       array = arrayFilter(array, function(group) {
8505         if (isArrayLikeObject(group)) {
8506           length = nativeMax(group.length, length);
8507           return true;
8508         }
8509       });
8510       return baseTimes(length, function(index) {
8511         return arrayMap(array, baseProperty(index));
8512       });
8513     }
8514
8515     /**
8516      * This method is like `_.unzip` except that it accepts `iteratee` to specify
8517      * how regrouped values should be combined. The iteratee is invoked with the
8518      * elements of each group: (...group).
8519      *
8520      * @static
8521      * @memberOf _
8522      * @since 3.8.0
8523      * @category Array
8524      * @param {Array} array The array of grouped elements to process.
8525      * @param {Function} [iteratee=_.identity] The function to combine
8526      *  regrouped values.
8527      * @returns {Array} Returns the new array of regrouped elements.
8528      * @example
8529      *
8530      * var zipped = _.zip([1, 2], [10, 20], [100, 200]);
8531      * // => [[1, 10, 100], [2, 20, 200]]
8532      *
8533      * _.unzipWith(zipped, _.add);
8534      * // => [3, 30, 300]
8535      */
8536     function unzipWith(array, iteratee) {
8537       if (!(array && array.length)) {
8538         return [];
8539       }
8540       var result = unzip(array);
8541       if (iteratee == null) {
8542         return result;
8543       }
8544       return arrayMap(result, function(group) {
8545         return apply(iteratee, undefined, group);
8546       });
8547     }
8548
8549     /**
8550      * Creates an array excluding all given values using
8551      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
8552      * for equality comparisons.
8553      *
8554      * **Note:** Unlike `_.pull`, this method returns a new array.
8555      *
8556      * @static
8557      * @memberOf _
8558      * @since 0.1.0
8559      * @category Array
8560      * @param {Array} array The array to inspect.
8561      * @param {...*} [values] The values to exclude.
8562      * @returns {Array} Returns the new array of filtered values.
8563      * @see _.difference, _.xor
8564      * @example
8565      *
8566      * _.without([2, 1, 2, 3], 1, 2);
8567      * // => [3]
8568      */
8569     var without = baseRest(function(array, values) {
8570       return isArrayLikeObject(array)
8571         ? baseDifference(array, values)
8572         : [];
8573     });
8574
8575     /**
8576      * Creates an array of unique values that is the
8577      * [symmetric difference](https://en.wikipedia.org/wiki/Symmetric_difference)
8578      * of the given arrays. The order of result values is determined by the order
8579      * they occur in the arrays.
8580      *
8581      * @static
8582      * @memberOf _
8583      * @since 2.4.0
8584      * @category Array
8585      * @param {...Array} [arrays] The arrays to inspect.
8586      * @returns {Array} Returns the new array of filtered values.
8587      * @see _.difference, _.without
8588      * @example
8589      *
8590      * _.xor([2, 1], [2, 3]);
8591      * // => [1, 3]
8592      */
8593     var xor = baseRest(function(arrays) {
8594       return baseXor(arrayFilter(arrays, isArrayLikeObject));
8595     });
8596
8597     /**
8598      * This method is like `_.xor` except that it accepts `iteratee` which is
8599      * invoked for each element of each `arrays` to generate the criterion by
8600      * which by which they're compared. The order of result values is determined
8601      * by the order they occur in the arrays. The iteratee is invoked with one
8602      * argument: (value).
8603      *
8604      * @static
8605      * @memberOf _
8606      * @since 4.0.0
8607      * @category Array
8608      * @param {...Array} [arrays] The arrays to inspect.
8609      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
8610      * @returns {Array} Returns the new array of filtered values.
8611      * @example
8612      *
8613      * _.xorBy([2.1, 1.2], [2.3, 3.4], Math.floor);
8614      * // => [1.2, 3.4]
8615      *
8616      * // The `_.property` iteratee shorthand.
8617      * _.xorBy([{ 'x': 1 }], [{ 'x': 2 }, { 'x': 1 }], 'x');
8618      * // => [{ 'x': 2 }]
8619      */
8620     var xorBy = baseRest(function(arrays) {
8621       var iteratee = last(arrays);
8622       if (isArrayLikeObject(iteratee)) {
8623         iteratee = undefined;
8624       }
8625       return baseXor(arrayFilter(arrays, isArrayLikeObject), getIteratee(iteratee, 2));
8626     });
8627
8628     /**
8629      * This method is like `_.xor` except that it accepts `comparator` which is
8630      * invoked to compare elements of `arrays`. The order of result values is
8631      * determined by the order they occur in the arrays. The comparator is invoked
8632      * with two arguments: (arrVal, othVal).
8633      *
8634      * @static
8635      * @memberOf _
8636      * @since 4.0.0
8637      * @category Array
8638      * @param {...Array} [arrays] The arrays to inspect.
8639      * @param {Function} [comparator] The comparator invoked per element.
8640      * @returns {Array} Returns the new array of filtered values.
8641      * @example
8642      *
8643      * var objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }];
8644      * var others = [{ 'x': 1, 'y': 1 }, { 'x': 1, 'y': 2 }];
8645      *
8646      * _.xorWith(objects, others, _.isEqual);
8647      * // => [{ 'x': 2, 'y': 1 }, { 'x': 1, 'y': 1 }]
8648      */
8649     var xorWith = baseRest(function(arrays) {
8650       var comparator = last(arrays);
8651       comparator = typeof comparator == 'function' ? comparator : undefined;
8652       return baseXor(arrayFilter(arrays, isArrayLikeObject), undefined, comparator);
8653     });
8654
8655     /**
8656      * Creates an array of grouped elements, the first of which contains the
8657      * first elements of the given arrays, the second of which contains the
8658      * second elements of the given arrays, and so on.
8659      *
8660      * @static
8661      * @memberOf _
8662      * @since 0.1.0
8663      * @category Array
8664      * @param {...Array} [arrays] The arrays to process.
8665      * @returns {Array} Returns the new array of grouped elements.
8666      * @example
8667      *
8668      * _.zip(['a', 'b'], [1, 2], [true, false]);
8669      * // => [['a', 1, true], ['b', 2, false]]
8670      */
8671     var zip = baseRest(unzip);
8672
8673     /**
8674      * This method is like `_.fromPairs` except that it accepts two arrays,
8675      * one of property identifiers and one of corresponding values.
8676      *
8677      * @static
8678      * @memberOf _
8679      * @since 0.4.0
8680      * @category Array
8681      * @param {Array} [props=[]] The property identifiers.
8682      * @param {Array} [values=[]] The property values.
8683      * @returns {Object} Returns the new object.
8684      * @example
8685      *
8686      * _.zipObject(['a', 'b'], [1, 2]);
8687      * // => { 'a': 1, 'b': 2 }
8688      */
8689     function zipObject(props, values) {
8690       return baseZipObject(props || [], values || [], assignValue);
8691     }
8692
8693     /**
8694      * This method is like `_.zipObject` except that it supports property paths.
8695      *
8696      * @static
8697      * @memberOf _
8698      * @since 4.1.0
8699      * @category Array
8700      * @param {Array} [props=[]] The property identifiers.
8701      * @param {Array} [values=[]] The property values.
8702      * @returns {Object} Returns the new object.
8703      * @example
8704      *
8705      * _.zipObjectDeep(['a.b[0].c', 'a.b[1].d'], [1, 2]);
8706      * // => { 'a': { 'b': [{ 'c': 1 }, { 'd': 2 }] } }
8707      */
8708     function zipObjectDeep(props, values) {
8709       return baseZipObject(props || [], values || [], baseSet);
8710     }
8711
8712     /**
8713      * This method is like `_.zip` except that it accepts `iteratee` to specify
8714      * how grouped values should be combined. The iteratee is invoked with the
8715      * elements of each group: (...group).
8716      *
8717      * @static
8718      * @memberOf _
8719      * @since 3.8.0
8720      * @category Array
8721      * @param {...Array} [arrays] The arrays to process.
8722      * @param {Function} [iteratee=_.identity] The function to combine
8723      *  grouped values.
8724      * @returns {Array} Returns the new array of grouped elements.
8725      * @example
8726      *
8727      * _.zipWith([1, 2], [10, 20], [100, 200], function(a, b, c) {
8728      *   return a + b + c;
8729      * });
8730      * // => [111, 222]
8731      */
8732     var zipWith = baseRest(function(arrays) {
8733       var length = arrays.length,
8734           iteratee = length > 1 ? arrays[length - 1] : undefined;
8735
8736       iteratee = typeof iteratee == 'function' ? (arrays.pop(), iteratee) : undefined;
8737       return unzipWith(arrays, iteratee);
8738     });
8739
8740     /*------------------------------------------------------------------------*/
8741
8742     /**
8743      * Creates a `lodash` wrapper instance that wraps `value` with explicit method
8744      * chain sequences enabled. The result of such sequences must be unwrapped
8745      * with `_#value`.
8746      *
8747      * @static
8748      * @memberOf _
8749      * @since 1.3.0
8750      * @category Seq
8751      * @param {*} value The value to wrap.
8752      * @returns {Object} Returns the new `lodash` wrapper instance.
8753      * @example
8754      *
8755      * var users = [
8756      *   { 'user': 'barney',  'age': 36 },
8757      *   { 'user': 'fred',    'age': 40 },
8758      *   { 'user': 'pebbles', 'age': 1 }
8759      * ];
8760      *
8761      * var youngest = _
8762      *   .chain(users)
8763      *   .sortBy('age')
8764      *   .map(function(o) {
8765      *     return o.user + ' is ' + o.age;
8766      *   })
8767      *   .head()
8768      *   .value();
8769      * // => 'pebbles is 1'
8770      */
8771     function chain(value) {
8772       var result = lodash(value);
8773       result.__chain__ = true;
8774       return result;
8775     }
8776
8777     /**
8778      * This method invokes `interceptor` and returns `value`. The interceptor
8779      * is invoked with one argument; (value). The purpose of this method is to
8780      * "tap into" a method chain sequence in order to modify intermediate results.
8781      *
8782      * @static
8783      * @memberOf _
8784      * @since 0.1.0
8785      * @category Seq
8786      * @param {*} value The value to provide to `interceptor`.
8787      * @param {Function} interceptor The function to invoke.
8788      * @returns {*} Returns `value`.
8789      * @example
8790      *
8791      * _([1, 2, 3])
8792      *  .tap(function(array) {
8793      *    // Mutate input array.
8794      *    array.pop();
8795      *  })
8796      *  .reverse()
8797      *  .value();
8798      * // => [2, 1]
8799      */
8800     function tap(value, interceptor) {
8801       interceptor(value);
8802       return value;
8803     }
8804
8805     /**
8806      * This method is like `_.tap` except that it returns the result of `interceptor`.
8807      * The purpose of this method is to "pass thru" values replacing intermediate
8808      * results in a method chain sequence.
8809      *
8810      * @static
8811      * @memberOf _
8812      * @since 3.0.0
8813      * @category Seq
8814      * @param {*} value The value to provide to `interceptor`.
8815      * @param {Function} interceptor The function to invoke.
8816      * @returns {*} Returns the result of `interceptor`.
8817      * @example
8818      *
8819      * _('  abc  ')
8820      *  .chain()
8821      *  .trim()
8822      *  .thru(function(value) {
8823      *    return [value];
8824      *  })
8825      *  .value();
8826      * // => ['abc']
8827      */
8828     function thru(value, interceptor) {
8829       return interceptor(value);
8830     }
8831
8832     /**
8833      * This method is the wrapper version of `_.at`.
8834      *
8835      * @name at
8836      * @memberOf _
8837      * @since 1.0.0
8838      * @category Seq
8839      * @param {...(string|string[])} [paths] The property paths to pick.
8840      * @returns {Object} Returns the new `lodash` wrapper instance.
8841      * @example
8842      *
8843      * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
8844      *
8845      * _(object).at(['a[0].b.c', 'a[1]']).value();
8846      * // => [3, 4]
8847      */
8848     var wrapperAt = flatRest(function(paths) {
8849       var length = paths.length,
8850           start = length ? paths[0] : 0,
8851           value = this.__wrapped__,
8852           interceptor = function(object) { return baseAt(object, paths); };
8853
8854       if (length > 1 || this.__actions__.length ||
8855           !(value instanceof LazyWrapper) || !isIndex(start)) {
8856         return this.thru(interceptor);
8857       }
8858       value = value.slice(start, +start + (length ? 1 : 0));
8859       value.__actions__.push({
8860         'func': thru,
8861         'args': [interceptor],
8862         'thisArg': undefined
8863       });
8864       return new LodashWrapper(value, this.__chain__).thru(function(array) {
8865         if (length && !array.length) {
8866           array.push(undefined);
8867         }
8868         return array;
8869       });
8870     });
8871
8872     /**
8873      * Creates a `lodash` wrapper instance with explicit method chain sequences enabled.
8874      *
8875      * @name chain
8876      * @memberOf _
8877      * @since 0.1.0
8878      * @category Seq
8879      * @returns {Object} Returns the new `lodash` wrapper instance.
8880      * @example
8881      *
8882      * var users = [
8883      *   { 'user': 'barney', 'age': 36 },
8884      *   { 'user': 'fred',   'age': 40 }
8885      * ];
8886      *
8887      * // A sequence without explicit chaining.
8888      * _(users).head();
8889      * // => { 'user': 'barney', 'age': 36 }
8890      *
8891      * // A sequence with explicit chaining.
8892      * _(users)
8893      *   .chain()
8894      *   .head()
8895      *   .pick('user')
8896      *   .value();
8897      * // => { 'user': 'barney' }
8898      */
8899     function wrapperChain() {
8900       return chain(this);
8901     }
8902
8903     /**
8904      * Executes the chain sequence and returns the wrapped result.
8905      *
8906      * @name commit
8907      * @memberOf _
8908      * @since 3.2.0
8909      * @category Seq
8910      * @returns {Object} Returns the new `lodash` wrapper instance.
8911      * @example
8912      *
8913      * var array = [1, 2];
8914      * var wrapped = _(array).push(3);
8915      *
8916      * console.log(array);
8917      * // => [1, 2]
8918      *
8919      * wrapped = wrapped.commit();
8920      * console.log(array);
8921      * // => [1, 2, 3]
8922      *
8923      * wrapped.last();
8924      * // => 3
8925      *
8926      * console.log(array);
8927      * // => [1, 2, 3]
8928      */
8929     function wrapperCommit() {
8930       return new LodashWrapper(this.value(), this.__chain__);
8931     }
8932
8933     /**
8934      * Gets the next value on a wrapped object following the
8935      * [iterator protocol](https://mdn.io/iteration_protocols#iterator).
8936      *
8937      * @name next
8938      * @memberOf _
8939      * @since 4.0.0
8940      * @category Seq
8941      * @returns {Object} Returns the next iterator value.
8942      * @example
8943      *
8944      * var wrapped = _([1, 2]);
8945      *
8946      * wrapped.next();
8947      * // => { 'done': false, 'value': 1 }
8948      *
8949      * wrapped.next();
8950      * // => { 'done': false, 'value': 2 }
8951      *
8952      * wrapped.next();
8953      * // => { 'done': true, 'value': undefined }
8954      */
8955     function wrapperNext() {
8956       if (this.__values__ === undefined) {
8957         this.__values__ = toArray(this.value());
8958       }
8959       var done = this.__index__ >= this.__values__.length,
8960           value = done ? undefined : this.__values__[this.__index__++];
8961
8962       return { 'done': done, 'value': value };
8963     }
8964
8965     /**
8966      * Enables the wrapper to be iterable.
8967      *
8968      * @name Symbol.iterator
8969      * @memberOf _
8970      * @since 4.0.0
8971      * @category Seq
8972      * @returns {Object} Returns the wrapper object.
8973      * @example
8974      *
8975      * var wrapped = _([1, 2]);
8976      *
8977      * wrapped[Symbol.iterator]() === wrapped;
8978      * // => true
8979      *
8980      * Array.from(wrapped);
8981      * // => [1, 2]
8982      */
8983     function wrapperToIterator() {
8984       return this;
8985     }
8986
8987     /**
8988      * Creates a clone of the chain sequence planting `value` as the wrapped value.
8989      *
8990      * @name plant
8991      * @memberOf _
8992      * @since 3.2.0
8993      * @category Seq
8994      * @param {*} value The value to plant.
8995      * @returns {Object} Returns the new `lodash` wrapper instance.
8996      * @example
8997      *
8998      * function square(n) {
8999      *   return n * n;
9000      * }
9001      *
9002      * var wrapped = _([1, 2]).map(square);
9003      * var other = wrapped.plant([3, 4]);
9004      *
9005      * other.value();
9006      * // => [9, 16]
9007      *
9008      * wrapped.value();
9009      * // => [1, 4]
9010      */
9011     function wrapperPlant(value) {
9012       var result,
9013           parent = this;
9014
9015       while (parent instanceof baseLodash) {
9016         var clone = wrapperClone(parent);
9017         clone.__index__ = 0;
9018         clone.__values__ = undefined;
9019         if (result) {
9020           previous.__wrapped__ = clone;
9021         } else {
9022           result = clone;
9023         }
9024         var previous = clone;
9025         parent = parent.__wrapped__;
9026       }
9027       previous.__wrapped__ = value;
9028       return result;
9029     }
9030
9031     /**
9032      * This method is the wrapper version of `_.reverse`.
9033      *
9034      * **Note:** This method mutates the wrapped array.
9035      *
9036      * @name reverse
9037      * @memberOf _
9038      * @since 0.1.0
9039      * @category Seq
9040      * @returns {Object} Returns the new `lodash` wrapper instance.
9041      * @example
9042      *
9043      * var array = [1, 2, 3];
9044      *
9045      * _(array).reverse().value()
9046      * // => [3, 2, 1]
9047      *
9048      * console.log(array);
9049      * // => [3, 2, 1]
9050      */
9051     function wrapperReverse() {
9052       var value = this.__wrapped__;
9053       if (value instanceof LazyWrapper) {
9054         var wrapped = value;
9055         if (this.__actions__.length) {
9056           wrapped = new LazyWrapper(this);
9057         }
9058         wrapped = wrapped.reverse();
9059         wrapped.__actions__.push({
9060           'func': thru,
9061           'args': [reverse],
9062           'thisArg': undefined
9063         });
9064         return new LodashWrapper(wrapped, this.__chain__);
9065       }
9066       return this.thru(reverse);
9067     }
9068
9069     /**
9070      * Executes the chain sequence to resolve the unwrapped value.
9071      *
9072      * @name value
9073      * @memberOf _
9074      * @since 0.1.0
9075      * @alias toJSON, valueOf
9076      * @category Seq
9077      * @returns {*} Returns the resolved unwrapped value.
9078      * @example
9079      *
9080      * _([1, 2, 3]).value();
9081      * // => [1, 2, 3]
9082      */
9083     function wrapperValue() {
9084       return baseWrapperValue(this.__wrapped__, this.__actions__);
9085     }
9086
9087     /*------------------------------------------------------------------------*/
9088
9089     /**
9090      * Creates an object composed of keys generated from the results of running
9091      * each element of `collection` thru `iteratee`. The corresponding value of
9092      * each key is the number of times the key was returned by `iteratee`. The
9093      * iteratee is invoked with one argument: (value).
9094      *
9095      * @static
9096      * @memberOf _
9097      * @since 0.5.0
9098      * @category Collection
9099      * @param {Array|Object} collection The collection to iterate over.
9100      * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
9101      * @returns {Object} Returns the composed aggregate object.
9102      * @example
9103      *
9104      * _.countBy([6.1, 4.2, 6.3], Math.floor);
9105      * // => { '4': 1, '6': 2 }
9106      *
9107      * // The `_.property` iteratee shorthand.
9108      * _.countBy(['one', 'two', 'three'], 'length');
9109      * // => { '3': 2, '5': 1 }
9110      */
9111     var countBy = createAggregator(function(result, value, key) {
9112       if (hasOwnProperty.call(result, key)) {
9113         ++result[key];
9114       } else {
9115         baseAssignValue(result, key, 1);
9116       }
9117     });
9118
9119     /**
9120      * Checks if `predicate` returns truthy for **all** elements of `collection`.
9121      * Iteration is stopped once `predicate` returns falsey. The predicate is
9122      * invoked with three arguments: (value, index|key, collection).
9123      *
9124      * **Note:** This method returns `true` for
9125      * [empty collections](https://en.wikipedia.org/wiki/Empty_set) because
9126      * [everything is true](https://en.wikipedia.org/wiki/Vacuous_truth) of
9127      * elements of empty collections.
9128      *
9129      * @static
9130      * @memberOf _
9131      * @since 0.1.0
9132      * @category Collection
9133      * @param {Array|Object} collection The collection to iterate over.
9134      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9135      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
9136      * @returns {boolean} Returns `true` if all elements pass the predicate check,
9137      *  else `false`.
9138      * @example
9139      *
9140      * _.every([true, 1, null, 'yes'], Boolean);
9141      * // => false
9142      *
9143      * var users = [
9144      *   { 'user': 'barney', 'age': 36, 'active': false },
9145      *   { 'user': 'fred',   'age': 40, 'active': false }
9146      * ];
9147      *
9148      * // The `_.matches` iteratee shorthand.
9149      * _.every(users, { 'user': 'barney', 'active': false });
9150      * // => false
9151      *
9152      * // The `_.matchesProperty` iteratee shorthand.
9153      * _.every(users, ['active', false]);
9154      * // => true
9155      *
9156      * // The `_.property` iteratee shorthand.
9157      * _.every(users, 'active');
9158      * // => false
9159      */
9160     function every(collection, predicate, guard) {
9161       var func = isArray(collection) ? arrayEvery : baseEvery;
9162       if (guard && isIterateeCall(collection, predicate, guard)) {
9163         predicate = undefined;
9164       }
9165       return func(collection, getIteratee(predicate, 3));
9166     }
9167
9168     /**
9169      * Iterates over elements of `collection`, returning an array of all elements
9170      * `predicate` returns truthy for. The predicate is invoked with three
9171      * arguments: (value, index|key, collection).
9172      *
9173      * **Note:** Unlike `_.remove`, this method returns a new array.
9174      *
9175      * @static
9176      * @memberOf _
9177      * @since 0.1.0
9178      * @category Collection
9179      * @param {Array|Object} collection The collection to iterate over.
9180      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9181      * @returns {Array} Returns the new filtered array.
9182      * @see _.reject
9183      * @example
9184      *
9185      * var users = [
9186      *   { 'user': 'barney', 'age': 36, 'active': true },
9187      *   { 'user': 'fred',   'age': 40, 'active': false }
9188      * ];
9189      *
9190      * _.filter(users, function(o) { return !o.active; });
9191      * // => objects for ['fred']
9192      *
9193      * // The `_.matches` iteratee shorthand.
9194      * _.filter(users, { 'age': 36, 'active': true });
9195      * // => objects for ['barney']
9196      *
9197      * // The `_.matchesProperty` iteratee shorthand.
9198      * _.filter(users, ['active', false]);
9199      * // => objects for ['fred']
9200      *
9201      * // The `_.property` iteratee shorthand.
9202      * _.filter(users, 'active');
9203      * // => objects for ['barney']
9204      */
9205     function filter(collection, predicate) {
9206       var func = isArray(collection) ? arrayFilter : baseFilter;
9207       return func(collection, getIteratee(predicate, 3));
9208     }
9209
9210     /**
9211      * Iterates over elements of `collection`, returning the first element
9212      * `predicate` returns truthy for. The predicate is invoked with three
9213      * arguments: (value, index|key, collection).
9214      *
9215      * @static
9216      * @memberOf _
9217      * @since 0.1.0
9218      * @category Collection
9219      * @param {Array|Object} collection The collection to inspect.
9220      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9221      * @param {number} [fromIndex=0] The index to search from.
9222      * @returns {*} Returns the matched element, else `undefined`.
9223      * @example
9224      *
9225      * var users = [
9226      *   { 'user': 'barney',  'age': 36, 'active': true },
9227      *   { 'user': 'fred',    'age': 40, 'active': false },
9228      *   { 'user': 'pebbles', 'age': 1,  'active': true }
9229      * ];
9230      *
9231      * _.find(users, function(o) { return o.age < 40; });
9232      * // => object for 'barney'
9233      *
9234      * // The `_.matches` iteratee shorthand.
9235      * _.find(users, { 'age': 1, 'active': true });
9236      * // => object for 'pebbles'
9237      *
9238      * // The `_.matchesProperty` iteratee shorthand.
9239      * _.find(users, ['active', false]);
9240      * // => object for 'fred'
9241      *
9242      * // The `_.property` iteratee shorthand.
9243      * _.find(users, 'active');
9244      * // => object for 'barney'
9245      */
9246     var find = createFind(findIndex);
9247
9248     /**
9249      * This method is like `_.find` except that it iterates over elements of
9250      * `collection` from right to left.
9251      *
9252      * @static
9253      * @memberOf _
9254      * @since 2.0.0
9255      * @category Collection
9256      * @param {Array|Object} collection The collection to inspect.
9257      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9258      * @param {number} [fromIndex=collection.length-1] The index to search from.
9259      * @returns {*} Returns the matched element, else `undefined`.
9260      * @example
9261      *
9262      * _.findLast([1, 2, 3, 4], function(n) {
9263      *   return n % 2 == 1;
9264      * });
9265      * // => 3
9266      */
9267     var findLast = createFind(findLastIndex);
9268
9269     /**
9270      * Creates a flattened array of values by running each element in `collection`
9271      * thru `iteratee` and flattening the mapped results. The iteratee is invoked
9272      * with three arguments: (value, index|key, collection).
9273      *
9274      * @static
9275      * @memberOf _
9276      * @since 4.0.0
9277      * @category Collection
9278      * @param {Array|Object} collection The collection to iterate over.
9279      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9280      * @returns {Array} Returns the new flattened array.
9281      * @example
9282      *
9283      * function duplicate(n) {
9284      *   return [n, n];
9285      * }
9286      *
9287      * _.flatMap([1, 2], duplicate);
9288      * // => [1, 1, 2, 2]
9289      */
9290     function flatMap(collection, iteratee) {
9291       return baseFlatten(map(collection, iteratee), 1);
9292     }
9293
9294     /**
9295      * This method is like `_.flatMap` except that it recursively flattens the
9296      * mapped results.
9297      *
9298      * @static
9299      * @memberOf _
9300      * @since 4.7.0
9301      * @category Collection
9302      * @param {Array|Object} collection The collection to iterate over.
9303      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9304      * @returns {Array} Returns the new flattened array.
9305      * @example
9306      *
9307      * function duplicate(n) {
9308      *   return [[[n, n]]];
9309      * }
9310      *
9311      * _.flatMapDeep([1, 2], duplicate);
9312      * // => [1, 1, 2, 2]
9313      */
9314     function flatMapDeep(collection, iteratee) {
9315       return baseFlatten(map(collection, iteratee), INFINITY);
9316     }
9317
9318     /**
9319      * This method is like `_.flatMap` except that it recursively flattens the
9320      * mapped results up to `depth` times.
9321      *
9322      * @static
9323      * @memberOf _
9324      * @since 4.7.0
9325      * @category Collection
9326      * @param {Array|Object} collection The collection to iterate over.
9327      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9328      * @param {number} [depth=1] The maximum recursion depth.
9329      * @returns {Array} Returns the new flattened array.
9330      * @example
9331      *
9332      * function duplicate(n) {
9333      *   return [[[n, n]]];
9334      * }
9335      *
9336      * _.flatMapDepth([1, 2], duplicate, 2);
9337      * // => [[1, 1], [2, 2]]
9338      */
9339     function flatMapDepth(collection, iteratee, depth) {
9340       depth = depth === undefined ? 1 : toInteger(depth);
9341       return baseFlatten(map(collection, iteratee), depth);
9342     }
9343
9344     /**
9345      * Iterates over elements of `collection` and invokes `iteratee` for each element.
9346      * The iteratee is invoked with three arguments: (value, index|key, collection).
9347      * Iteratee functions may exit iteration early by explicitly returning `false`.
9348      *
9349      * **Note:** As with other "Collections" methods, objects with a "length"
9350      * property are iterated like arrays. To avoid this behavior use `_.forIn`
9351      * or `_.forOwn` for object iteration.
9352      *
9353      * @static
9354      * @memberOf _
9355      * @since 0.1.0
9356      * @alias each
9357      * @category Collection
9358      * @param {Array|Object} collection The collection to iterate over.
9359      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9360      * @returns {Array|Object} Returns `collection`.
9361      * @see _.forEachRight
9362      * @example
9363      *
9364      * _.forEach([1, 2], function(value) {
9365      *   console.log(value);
9366      * });
9367      * // => Logs `1` then `2`.
9368      *
9369      * _.forEach({ 'a': 1, 'b': 2 }, function(value, key) {
9370      *   console.log(key);
9371      * });
9372      * // => Logs 'a' then 'b' (iteration order is not guaranteed).
9373      */
9374     function forEach(collection, iteratee) {
9375       var func = isArray(collection) ? arrayEach : baseEach;
9376       return func(collection, getIteratee(iteratee, 3));
9377     }
9378
9379     /**
9380      * This method is like `_.forEach` except that it iterates over elements of
9381      * `collection` from right to left.
9382      *
9383      * @static
9384      * @memberOf _
9385      * @since 2.0.0
9386      * @alias eachRight
9387      * @category Collection
9388      * @param {Array|Object} collection The collection to iterate over.
9389      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9390      * @returns {Array|Object} Returns `collection`.
9391      * @see _.forEach
9392      * @example
9393      *
9394      * _.forEachRight([1, 2], function(value) {
9395      *   console.log(value);
9396      * });
9397      * // => Logs `2` then `1`.
9398      */
9399     function forEachRight(collection, iteratee) {
9400       var func = isArray(collection) ? arrayEachRight : baseEachRight;
9401       return func(collection, getIteratee(iteratee, 3));
9402     }
9403
9404     /**
9405      * Creates an object composed of keys generated from the results of running
9406      * each element of `collection` thru `iteratee`. The order of grouped values
9407      * is determined by the order they occur in `collection`. The corresponding
9408      * value of each key is an array of elements responsible for generating the
9409      * key. The iteratee is invoked with one argument: (value).
9410      *
9411      * @static
9412      * @memberOf _
9413      * @since 0.1.0
9414      * @category Collection
9415      * @param {Array|Object} collection The collection to iterate over.
9416      * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
9417      * @returns {Object} Returns the composed aggregate object.
9418      * @example
9419      *
9420      * _.groupBy([6.1, 4.2, 6.3], Math.floor);
9421      * // => { '4': [4.2], '6': [6.1, 6.3] }
9422      *
9423      * // The `_.property` iteratee shorthand.
9424      * _.groupBy(['one', 'two', 'three'], 'length');
9425      * // => { '3': ['one', 'two'], '5': ['three'] }
9426      */
9427     var groupBy = createAggregator(function(result, value, key) {
9428       if (hasOwnProperty.call(result, key)) {
9429         result[key].push(value);
9430       } else {
9431         baseAssignValue(result, key, [value]);
9432       }
9433     });
9434
9435     /**
9436      * Checks if `value` is in `collection`. If `collection` is a string, it's
9437      * checked for a substring of `value`, otherwise
9438      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
9439      * is used for equality comparisons. If `fromIndex` is negative, it's used as
9440      * the offset from the end of `collection`.
9441      *
9442      * @static
9443      * @memberOf _
9444      * @since 0.1.0
9445      * @category Collection
9446      * @param {Array|Object|string} collection The collection to inspect.
9447      * @param {*} value The value to search for.
9448      * @param {number} [fromIndex=0] The index to search from.
9449      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
9450      * @returns {boolean} Returns `true` if `value` is found, else `false`.
9451      * @example
9452      *
9453      * _.includes([1, 2, 3], 1);
9454      * // => true
9455      *
9456      * _.includes([1, 2, 3], 1, 2);
9457      * // => false
9458      *
9459      * _.includes({ 'a': 1, 'b': 2 }, 1);
9460      * // => true
9461      *
9462      * _.includes('abcd', 'bc');
9463      * // => true
9464      */
9465     function includes(collection, value, fromIndex, guard) {
9466       collection = isArrayLike(collection) ? collection : values(collection);
9467       fromIndex = (fromIndex && !guard) ? toInteger(fromIndex) : 0;
9468
9469       var length = collection.length;
9470       if (fromIndex < 0) {
9471         fromIndex = nativeMax(length + fromIndex, 0);
9472       }
9473       return isString(collection)
9474         ? (fromIndex <= length && collection.indexOf(value, fromIndex) > -1)
9475         : (!!length && baseIndexOf(collection, value, fromIndex) > -1);
9476     }
9477
9478     /**
9479      * Invokes the method at `path` of each element in `collection`, returning
9480      * an array of the results of each invoked method. Any additional arguments
9481      * are provided to each invoked method. If `path` is a function, it's invoked
9482      * for, and `this` bound to, each element in `collection`.
9483      *
9484      * @static
9485      * @memberOf _
9486      * @since 4.0.0
9487      * @category Collection
9488      * @param {Array|Object} collection The collection to iterate over.
9489      * @param {Array|Function|string} path The path of the method to invoke or
9490      *  the function invoked per iteration.
9491      * @param {...*} [args] The arguments to invoke each method with.
9492      * @returns {Array} Returns the array of results.
9493      * @example
9494      *
9495      * _.invokeMap([[5, 1, 7], [3, 2, 1]], 'sort');
9496      * // => [[1, 5, 7], [1, 2, 3]]
9497      *
9498      * _.invokeMap([123, 456], String.prototype.split, '');
9499      * // => [['1', '2', '3'], ['4', '5', '6']]
9500      */
9501     var invokeMap = baseRest(function(collection, path, args) {
9502       var index = -1,
9503           isFunc = typeof path == 'function',
9504           isProp = isKey(path),
9505           result = isArrayLike(collection) ? Array(collection.length) : [];
9506
9507       baseEach(collection, function(value) {
9508         var func = isFunc ? path : ((isProp && value != null) ? value[path] : undefined);
9509         result[++index] = func ? apply(func, value, args) : baseInvoke(value, path, args);
9510       });
9511       return result;
9512     });
9513
9514     /**
9515      * Creates an object composed of keys generated from the results of running
9516      * each element of `collection` thru `iteratee`. The corresponding value of
9517      * each key is the last element responsible for generating the key. The
9518      * iteratee is invoked with one argument: (value).
9519      *
9520      * @static
9521      * @memberOf _
9522      * @since 4.0.0
9523      * @category Collection
9524      * @param {Array|Object} collection The collection to iterate over.
9525      * @param {Function} [iteratee=_.identity] The iteratee to transform keys.
9526      * @returns {Object} Returns the composed aggregate object.
9527      * @example
9528      *
9529      * var array = [
9530      *   { 'dir': 'left', 'code': 97 },
9531      *   { 'dir': 'right', 'code': 100 }
9532      * ];
9533      *
9534      * _.keyBy(array, function(o) {
9535      *   return String.fromCharCode(o.code);
9536      * });
9537      * // => { 'a': { 'dir': 'left', 'code': 97 }, 'd': { 'dir': 'right', 'code': 100 } }
9538      *
9539      * _.keyBy(array, 'dir');
9540      * // => { 'left': { 'dir': 'left', 'code': 97 }, 'right': { 'dir': 'right', 'code': 100 } }
9541      */
9542     var keyBy = createAggregator(function(result, value, key) {
9543       baseAssignValue(result, key, value);
9544     });
9545
9546     /**
9547      * Creates an array of values by running each element in `collection` thru
9548      * `iteratee`. The iteratee is invoked with three arguments:
9549      * (value, index|key, collection).
9550      *
9551      * Many lodash methods are guarded to work as iteratees for methods like
9552      * `_.every`, `_.filter`, `_.map`, `_.mapValues`, `_.reject`, and `_.some`.
9553      *
9554      * The guarded methods are:
9555      * `ary`, `chunk`, `curry`, `curryRight`, `drop`, `dropRight`, `every`,
9556      * `fill`, `invert`, `parseInt`, `random`, `range`, `rangeRight`, `repeat`,
9557      * `sampleSize`, `slice`, `some`, `sortBy`, `split`, `take`, `takeRight`,
9558      * `template`, `trim`, `trimEnd`, `trimStart`, and `words`
9559      *
9560      * @static
9561      * @memberOf _
9562      * @since 0.1.0
9563      * @category Collection
9564      * @param {Array|Object} collection The collection to iterate over.
9565      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9566      * @returns {Array} Returns the new mapped array.
9567      * @example
9568      *
9569      * function square(n) {
9570      *   return n * n;
9571      * }
9572      *
9573      * _.map([4, 8], square);
9574      * // => [16, 64]
9575      *
9576      * _.map({ 'a': 4, 'b': 8 }, square);
9577      * // => [16, 64] (iteration order is not guaranteed)
9578      *
9579      * var users = [
9580      *   { 'user': 'barney' },
9581      *   { 'user': 'fred' }
9582      * ];
9583      *
9584      * // The `_.property` iteratee shorthand.
9585      * _.map(users, 'user');
9586      * // => ['barney', 'fred']
9587      */
9588     function map(collection, iteratee) {
9589       var func = isArray(collection) ? arrayMap : baseMap;
9590       return func(collection, getIteratee(iteratee, 3));
9591     }
9592
9593     /**
9594      * This method is like `_.sortBy` except that it allows specifying the sort
9595      * orders of the iteratees to sort by. If `orders` is unspecified, all values
9596      * are sorted in ascending order. Otherwise, specify an order of "desc" for
9597      * descending or "asc" for ascending sort order of corresponding values.
9598      *
9599      * @static
9600      * @memberOf _
9601      * @since 4.0.0
9602      * @category Collection
9603      * @param {Array|Object} collection The collection to iterate over.
9604      * @param {Array[]|Function[]|Object[]|string[]} [iteratees=[_.identity]]
9605      *  The iteratees to sort by.
9606      * @param {string[]} [orders] The sort orders of `iteratees`.
9607      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.reduce`.
9608      * @returns {Array} Returns the new sorted array.
9609      * @example
9610      *
9611      * var users = [
9612      *   { 'user': 'fred',   'age': 48 },
9613      *   { 'user': 'barney', 'age': 34 },
9614      *   { 'user': 'fred',   'age': 40 },
9615      *   { 'user': 'barney', 'age': 36 }
9616      * ];
9617      *
9618      * // Sort by `user` in ascending order and by `age` in descending order.
9619      * _.orderBy(users, ['user', 'age'], ['asc', 'desc']);
9620      * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
9621      */
9622     function orderBy(collection, iteratees, orders, guard) {
9623       if (collection == null) {
9624         return [];
9625       }
9626       if (!isArray(iteratees)) {
9627         iteratees = iteratees == null ? [] : [iteratees];
9628       }
9629       orders = guard ? undefined : orders;
9630       if (!isArray(orders)) {
9631         orders = orders == null ? [] : [orders];
9632       }
9633       return baseOrderBy(collection, iteratees, orders);
9634     }
9635
9636     /**
9637      * Creates an array of elements split into two groups, the first of which
9638      * contains elements `predicate` returns truthy for, the second of which
9639      * contains elements `predicate` returns falsey for. The predicate is
9640      * invoked with one argument: (value).
9641      *
9642      * @static
9643      * @memberOf _
9644      * @since 3.0.0
9645      * @category Collection
9646      * @param {Array|Object} collection The collection to iterate over.
9647      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9648      * @returns {Array} Returns the array of grouped elements.
9649      * @example
9650      *
9651      * var users = [
9652      *   { 'user': 'barney',  'age': 36, 'active': false },
9653      *   { 'user': 'fred',    'age': 40, 'active': true },
9654      *   { 'user': 'pebbles', 'age': 1,  'active': false }
9655      * ];
9656      *
9657      * _.partition(users, function(o) { return o.active; });
9658      * // => objects for [['fred'], ['barney', 'pebbles']]
9659      *
9660      * // The `_.matches` iteratee shorthand.
9661      * _.partition(users, { 'age': 1, 'active': false });
9662      * // => objects for [['pebbles'], ['barney', 'fred']]
9663      *
9664      * // The `_.matchesProperty` iteratee shorthand.
9665      * _.partition(users, ['active', false]);
9666      * // => objects for [['barney', 'pebbles'], ['fred']]
9667      *
9668      * // The `_.property` iteratee shorthand.
9669      * _.partition(users, 'active');
9670      * // => objects for [['fred'], ['barney', 'pebbles']]
9671      */
9672     var partition = createAggregator(function(result, value, key) {
9673       result[key ? 0 : 1].push(value);
9674     }, function() { return [[], []]; });
9675
9676     /**
9677      * Reduces `collection` to a value which is the accumulated result of running
9678      * each element in `collection` thru `iteratee`, where each successive
9679      * invocation is supplied the return value of the previous. If `accumulator`
9680      * is not given, the first element of `collection` is used as the initial
9681      * value. The iteratee is invoked with four arguments:
9682      * (accumulator, value, index|key, collection).
9683      *
9684      * Many lodash methods are guarded to work as iteratees for methods like
9685      * `_.reduce`, `_.reduceRight`, and `_.transform`.
9686      *
9687      * The guarded methods are:
9688      * `assign`, `defaults`, `defaultsDeep`, `includes`, `merge`, `orderBy`,
9689      * and `sortBy`
9690      *
9691      * @static
9692      * @memberOf _
9693      * @since 0.1.0
9694      * @category Collection
9695      * @param {Array|Object} collection The collection to iterate over.
9696      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9697      * @param {*} [accumulator] The initial value.
9698      * @returns {*} Returns the accumulated value.
9699      * @see _.reduceRight
9700      * @example
9701      *
9702      * _.reduce([1, 2], function(sum, n) {
9703      *   return sum + n;
9704      * }, 0);
9705      * // => 3
9706      *
9707      * _.reduce({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
9708      *   (result[value] || (result[value] = [])).push(key);
9709      *   return result;
9710      * }, {});
9711      * // => { '1': ['a', 'c'], '2': ['b'] } (iteration order is not guaranteed)
9712      */
9713     function reduce(collection, iteratee, accumulator) {
9714       var func = isArray(collection) ? arrayReduce : baseReduce,
9715           initAccum = arguments.length < 3;
9716
9717       return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEach);
9718     }
9719
9720     /**
9721      * This method is like `_.reduce` except that it iterates over elements of
9722      * `collection` from right to left.
9723      *
9724      * @static
9725      * @memberOf _
9726      * @since 0.1.0
9727      * @category Collection
9728      * @param {Array|Object} collection The collection to iterate over.
9729      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
9730      * @param {*} [accumulator] The initial value.
9731      * @returns {*} Returns the accumulated value.
9732      * @see _.reduce
9733      * @example
9734      *
9735      * var array = [[0, 1], [2, 3], [4, 5]];
9736      *
9737      * _.reduceRight(array, function(flattened, other) {
9738      *   return flattened.concat(other);
9739      * }, []);
9740      * // => [4, 5, 2, 3, 0, 1]
9741      */
9742     function reduceRight(collection, iteratee, accumulator) {
9743       var func = isArray(collection) ? arrayReduceRight : baseReduce,
9744           initAccum = arguments.length < 3;
9745
9746       return func(collection, getIteratee(iteratee, 4), accumulator, initAccum, baseEachRight);
9747     }
9748
9749     /**
9750      * The opposite of `_.filter`; this method returns the elements of `collection`
9751      * that `predicate` does **not** return truthy for.
9752      *
9753      * @static
9754      * @memberOf _
9755      * @since 0.1.0
9756      * @category Collection
9757      * @param {Array|Object} collection The collection to iterate over.
9758      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9759      * @returns {Array} Returns the new filtered array.
9760      * @see _.filter
9761      * @example
9762      *
9763      * var users = [
9764      *   { 'user': 'barney', 'age': 36, 'active': false },
9765      *   { 'user': 'fred',   'age': 40, 'active': true }
9766      * ];
9767      *
9768      * _.reject(users, function(o) { return !o.active; });
9769      * // => objects for ['fred']
9770      *
9771      * // The `_.matches` iteratee shorthand.
9772      * _.reject(users, { 'age': 40, 'active': true });
9773      * // => objects for ['barney']
9774      *
9775      * // The `_.matchesProperty` iteratee shorthand.
9776      * _.reject(users, ['active', false]);
9777      * // => objects for ['fred']
9778      *
9779      * // The `_.property` iteratee shorthand.
9780      * _.reject(users, 'active');
9781      * // => objects for ['barney']
9782      */
9783     function reject(collection, predicate) {
9784       var func = isArray(collection) ? arrayFilter : baseFilter;
9785       return func(collection, negate(getIteratee(predicate, 3)));
9786     }
9787
9788     /**
9789      * Gets a random element from `collection`.
9790      *
9791      * @static
9792      * @memberOf _
9793      * @since 2.0.0
9794      * @category Collection
9795      * @param {Array|Object} collection The collection to sample.
9796      * @returns {*} Returns the random element.
9797      * @example
9798      *
9799      * _.sample([1, 2, 3, 4]);
9800      * // => 2
9801      */
9802     function sample(collection) {
9803       var func = isArray(collection) ? arraySample : baseSample;
9804       return func(collection);
9805     }
9806
9807     /**
9808      * Gets `n` random elements at unique keys from `collection` up to the
9809      * size of `collection`.
9810      *
9811      * @static
9812      * @memberOf _
9813      * @since 4.0.0
9814      * @category Collection
9815      * @param {Array|Object} collection The collection to sample.
9816      * @param {number} [n=1] The number of elements to sample.
9817      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
9818      * @returns {Array} Returns the random elements.
9819      * @example
9820      *
9821      * _.sampleSize([1, 2, 3], 2);
9822      * // => [3, 1]
9823      *
9824      * _.sampleSize([1, 2, 3], 4);
9825      * // => [2, 3, 1]
9826      */
9827     function sampleSize(collection, n, guard) {
9828       if ((guard ? isIterateeCall(collection, n, guard) : n === undefined)) {
9829         n = 1;
9830       } else {
9831         n = toInteger(n);
9832       }
9833       var func = isArray(collection) ? arraySampleSize : baseSampleSize;
9834       return func(collection, n);
9835     }
9836
9837     /**
9838      * Creates an array of shuffled values, using a version of the
9839      * [Fisher-Yates shuffle](https://en.wikipedia.org/wiki/Fisher-Yates_shuffle).
9840      *
9841      * @static
9842      * @memberOf _
9843      * @since 0.1.0
9844      * @category Collection
9845      * @param {Array|Object} collection The collection to shuffle.
9846      * @returns {Array} Returns the new shuffled array.
9847      * @example
9848      *
9849      * _.shuffle([1, 2, 3, 4]);
9850      * // => [4, 1, 3, 2]
9851      */
9852     function shuffle(collection) {
9853       var func = isArray(collection) ? arrayShuffle : baseShuffle;
9854       return func(collection);
9855     }
9856
9857     /**
9858      * Gets the size of `collection` by returning its length for array-like
9859      * values or the number of own enumerable string keyed properties for objects.
9860      *
9861      * @static
9862      * @memberOf _
9863      * @since 0.1.0
9864      * @category Collection
9865      * @param {Array|Object|string} collection The collection to inspect.
9866      * @returns {number} Returns the collection size.
9867      * @example
9868      *
9869      * _.size([1, 2, 3]);
9870      * // => 3
9871      *
9872      * _.size({ 'a': 1, 'b': 2 });
9873      * // => 2
9874      *
9875      * _.size('pebbles');
9876      * // => 7
9877      */
9878     function size(collection) {
9879       if (collection == null) {
9880         return 0;
9881       }
9882       if (isArrayLike(collection)) {
9883         return isString(collection) ? stringSize(collection) : collection.length;
9884       }
9885       var tag = getTag(collection);
9886       if (tag == mapTag || tag == setTag) {
9887         return collection.size;
9888       }
9889       return baseKeys(collection).length;
9890     }
9891
9892     /**
9893      * Checks if `predicate` returns truthy for **any** element of `collection`.
9894      * Iteration is stopped once `predicate` returns truthy. The predicate is
9895      * invoked with three arguments: (value, index|key, collection).
9896      *
9897      * @static
9898      * @memberOf _
9899      * @since 0.1.0
9900      * @category Collection
9901      * @param {Array|Object} collection The collection to iterate over.
9902      * @param {Function} [predicate=_.identity] The function invoked per iteration.
9903      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
9904      * @returns {boolean} Returns `true` if any element passes the predicate check,
9905      *  else `false`.
9906      * @example
9907      *
9908      * _.some([null, 0, 'yes', false], Boolean);
9909      * // => true
9910      *
9911      * var users = [
9912      *   { 'user': 'barney', 'active': true },
9913      *   { 'user': 'fred',   'active': false }
9914      * ];
9915      *
9916      * // The `_.matches` iteratee shorthand.
9917      * _.some(users, { 'user': 'barney', 'active': false });
9918      * // => false
9919      *
9920      * // The `_.matchesProperty` iteratee shorthand.
9921      * _.some(users, ['active', false]);
9922      * // => true
9923      *
9924      * // The `_.property` iteratee shorthand.
9925      * _.some(users, 'active');
9926      * // => true
9927      */
9928     function some(collection, predicate, guard) {
9929       var func = isArray(collection) ? arraySome : baseSome;
9930       if (guard && isIterateeCall(collection, predicate, guard)) {
9931         predicate = undefined;
9932       }
9933       return func(collection, getIteratee(predicate, 3));
9934     }
9935
9936     /**
9937      * Creates an array of elements, sorted in ascending order by the results of
9938      * running each element in a collection thru each iteratee. This method
9939      * performs a stable sort, that is, it preserves the original sort order of
9940      * equal elements. The iteratees are invoked with one argument: (value).
9941      *
9942      * @static
9943      * @memberOf _
9944      * @since 0.1.0
9945      * @category Collection
9946      * @param {Array|Object} collection The collection to iterate over.
9947      * @param {...(Function|Function[])} [iteratees=[_.identity]]
9948      *  The iteratees to sort by.
9949      * @returns {Array} Returns the new sorted array.
9950      * @example
9951      *
9952      * var users = [
9953      *   { 'user': 'fred',   'age': 48 },
9954      *   { 'user': 'barney', 'age': 36 },
9955      *   { 'user': 'fred',   'age': 40 },
9956      *   { 'user': 'barney', 'age': 34 }
9957      * ];
9958      *
9959      * _.sortBy(users, [function(o) { return o.user; }]);
9960      * // => objects for [['barney', 36], ['barney', 34], ['fred', 48], ['fred', 40]]
9961      *
9962      * _.sortBy(users, ['user', 'age']);
9963      * // => objects for [['barney', 34], ['barney', 36], ['fred', 40], ['fred', 48]]
9964      */
9965     var sortBy = baseRest(function(collection, iteratees) {
9966       if (collection == null) {
9967         return [];
9968       }
9969       var length = iteratees.length;
9970       if (length > 1 && isIterateeCall(collection, iteratees[0], iteratees[1])) {
9971         iteratees = [];
9972       } else if (length > 2 && isIterateeCall(iteratees[0], iteratees[1], iteratees[2])) {
9973         iteratees = [iteratees[0]];
9974       }
9975       return baseOrderBy(collection, baseFlatten(iteratees, 1), []);
9976     });
9977
9978     /*------------------------------------------------------------------------*/
9979
9980     /**
9981      * Gets the timestamp of the number of milliseconds that have elapsed since
9982      * the Unix epoch (1 January 1970 00:00:00 UTC).
9983      *
9984      * @static
9985      * @memberOf _
9986      * @since 2.4.0
9987      * @category Date
9988      * @returns {number} Returns the timestamp.
9989      * @example
9990      *
9991      * _.defer(function(stamp) {
9992      *   console.log(_.now() - stamp);
9993      * }, _.now());
9994      * // => Logs the number of milliseconds it took for the deferred invocation.
9995      */
9996     var now = ctxNow || function() {
9997       return root.Date.now();
9998     };
9999
10000     /*------------------------------------------------------------------------*/
10001
10002     /**
10003      * The opposite of `_.before`; this method creates a function that invokes
10004      * `func` once it's called `n` or more times.
10005      *
10006      * @static
10007      * @memberOf _
10008      * @since 0.1.0
10009      * @category Function
10010      * @param {number} n The number of calls before `func` is invoked.
10011      * @param {Function} func The function to restrict.
10012      * @returns {Function} Returns the new restricted function.
10013      * @example
10014      *
10015      * var saves = ['profile', 'settings'];
10016      *
10017      * var done = _.after(saves.length, function() {
10018      *   console.log('done saving!');
10019      * });
10020      *
10021      * _.forEach(saves, function(type) {
10022      *   asyncSave({ 'type': type, 'complete': done });
10023      * });
10024      * // => Logs 'done saving!' after the two async saves have completed.
10025      */
10026     function after(n, func) {
10027       if (typeof func != 'function') {
10028         throw new TypeError(FUNC_ERROR_TEXT);
10029       }
10030       n = toInteger(n);
10031       return function() {
10032         if (--n < 1) {
10033           return func.apply(this, arguments);
10034         }
10035       };
10036     }
10037
10038     /**
10039      * Creates a function that invokes `func`, with up to `n` arguments,
10040      * ignoring any additional arguments.
10041      *
10042      * @static
10043      * @memberOf _
10044      * @since 3.0.0
10045      * @category Function
10046      * @param {Function} func The function to cap arguments for.
10047      * @param {number} [n=func.length] The arity cap.
10048      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
10049      * @returns {Function} Returns the new capped function.
10050      * @example
10051      *
10052      * _.map(['6', '8', '10'], _.ary(parseInt, 1));
10053      * // => [6, 8, 10]
10054      */
10055     function ary(func, n, guard) {
10056       n = guard ? undefined : n;
10057       n = (func && n == null) ? func.length : n;
10058       return createWrap(func, WRAP_ARY_FLAG, undefined, undefined, undefined, undefined, n);
10059     }
10060
10061     /**
10062      * Creates a function that invokes `func`, with the `this` binding and arguments
10063      * of the created function, while it's called less than `n` times. Subsequent
10064      * calls to the created function return the result of the last `func` invocation.
10065      *
10066      * @static
10067      * @memberOf _
10068      * @since 3.0.0
10069      * @category Function
10070      * @param {number} n The number of calls at which `func` is no longer invoked.
10071      * @param {Function} func The function to restrict.
10072      * @returns {Function} Returns the new restricted function.
10073      * @example
10074      *
10075      * jQuery(element).on('click', _.before(5, addContactToList));
10076      * // => Allows adding up to 4 contacts to the list.
10077      */
10078     function before(n, func) {
10079       var result;
10080       if (typeof func != 'function') {
10081         throw new TypeError(FUNC_ERROR_TEXT);
10082       }
10083       n = toInteger(n);
10084       return function() {
10085         if (--n > 0) {
10086           result = func.apply(this, arguments);
10087         }
10088         if (n <= 1) {
10089           func = undefined;
10090         }
10091         return result;
10092       };
10093     }
10094
10095     /**
10096      * Creates a function that invokes `func` with the `this` binding of `thisArg`
10097      * and `partials` prepended to the arguments it receives.
10098      *
10099      * The `_.bind.placeholder` value, which defaults to `_` in monolithic builds,
10100      * may be used as a placeholder for partially applied arguments.
10101      *
10102      * **Note:** Unlike native `Function#bind`, this method doesn't set the "length"
10103      * property of bound functions.
10104      *
10105      * @static
10106      * @memberOf _
10107      * @since 0.1.0
10108      * @category Function
10109      * @param {Function} func The function to bind.
10110      * @param {*} thisArg The `this` binding of `func`.
10111      * @param {...*} [partials] The arguments to be partially applied.
10112      * @returns {Function} Returns the new bound function.
10113      * @example
10114      *
10115      * function greet(greeting, punctuation) {
10116      *   return greeting + ' ' + this.user + punctuation;
10117      * }
10118      *
10119      * var object = { 'user': 'fred' };
10120      *
10121      * var bound = _.bind(greet, object, 'hi');
10122      * bound('!');
10123      * // => 'hi fred!'
10124      *
10125      * // Bound with placeholders.
10126      * var bound = _.bind(greet, object, _, '!');
10127      * bound('hi');
10128      * // => 'hi fred!'
10129      */
10130     var bind = baseRest(function(func, thisArg, partials) {
10131       var bitmask = WRAP_BIND_FLAG;
10132       if (partials.length) {
10133         var holders = replaceHolders(partials, getHolder(bind));
10134         bitmask |= WRAP_PARTIAL_FLAG;
10135       }
10136       return createWrap(func, bitmask, thisArg, partials, holders);
10137     });
10138
10139     /**
10140      * Creates a function that invokes the method at `object[key]` with `partials`
10141      * prepended to the arguments it receives.
10142      *
10143      * This method differs from `_.bind` by allowing bound functions to reference
10144      * methods that may be redefined or don't yet exist. See
10145      * [Peter Michaux's article](http://peter.michaux.ca/articles/lazy-function-definition-pattern)
10146      * for more details.
10147      *
10148      * The `_.bindKey.placeholder` value, which defaults to `_` in monolithic
10149      * builds, may be used as a placeholder for partially applied arguments.
10150      *
10151      * @static
10152      * @memberOf _
10153      * @since 0.10.0
10154      * @category Function
10155      * @param {Object} object The object to invoke the method on.
10156      * @param {string} key The key of the method.
10157      * @param {...*} [partials] The arguments to be partially applied.
10158      * @returns {Function} Returns the new bound function.
10159      * @example
10160      *
10161      * var object = {
10162      *   'user': 'fred',
10163      *   'greet': function(greeting, punctuation) {
10164      *     return greeting + ' ' + this.user + punctuation;
10165      *   }
10166      * };
10167      *
10168      * var bound = _.bindKey(object, 'greet', 'hi');
10169      * bound('!');
10170      * // => 'hi fred!'
10171      *
10172      * object.greet = function(greeting, punctuation) {
10173      *   return greeting + 'ya ' + this.user + punctuation;
10174      * };
10175      *
10176      * bound('!');
10177      * // => 'hiya fred!'
10178      *
10179      * // Bound with placeholders.
10180      * var bound = _.bindKey(object, 'greet', _, '!');
10181      * bound('hi');
10182      * // => 'hiya fred!'
10183      */
10184     var bindKey = baseRest(function(object, key, partials) {
10185       var bitmask = WRAP_BIND_FLAG | WRAP_BIND_KEY_FLAG;
10186       if (partials.length) {
10187         var holders = replaceHolders(partials, getHolder(bindKey));
10188         bitmask |= WRAP_PARTIAL_FLAG;
10189       }
10190       return createWrap(key, bitmask, object, partials, holders);
10191     });
10192
10193     /**
10194      * Creates a function that accepts arguments of `func` and either invokes
10195      * `func` returning its result, if at least `arity` number of arguments have
10196      * been provided, or returns a function that accepts the remaining `func`
10197      * arguments, and so on. The arity of `func` may be specified if `func.length`
10198      * is not sufficient.
10199      *
10200      * The `_.curry.placeholder` value, which defaults to `_` in monolithic builds,
10201      * may be used as a placeholder for provided arguments.
10202      *
10203      * **Note:** This method doesn't set the "length" property of curried functions.
10204      *
10205      * @static
10206      * @memberOf _
10207      * @since 2.0.0
10208      * @category Function
10209      * @param {Function} func The function to curry.
10210      * @param {number} [arity=func.length] The arity of `func`.
10211      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
10212      * @returns {Function} Returns the new curried function.
10213      * @example
10214      *
10215      * var abc = function(a, b, c) {
10216      *   return [a, b, c];
10217      * };
10218      *
10219      * var curried = _.curry(abc);
10220      *
10221      * curried(1)(2)(3);
10222      * // => [1, 2, 3]
10223      *
10224      * curried(1, 2)(3);
10225      * // => [1, 2, 3]
10226      *
10227      * curried(1, 2, 3);
10228      * // => [1, 2, 3]
10229      *
10230      * // Curried with placeholders.
10231      * curried(1)(_, 3)(2);
10232      * // => [1, 2, 3]
10233      */
10234     function curry(func, arity, guard) {
10235       arity = guard ? undefined : arity;
10236       var result = createWrap(func, WRAP_CURRY_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
10237       result.placeholder = curry.placeholder;
10238       return result;
10239     }
10240
10241     /**
10242      * This method is like `_.curry` except that arguments are applied to `func`
10243      * in the manner of `_.partialRight` instead of `_.partial`.
10244      *
10245      * The `_.curryRight.placeholder` value, which defaults to `_` in monolithic
10246      * builds, may be used as a placeholder for provided arguments.
10247      *
10248      * **Note:** This method doesn't set the "length" property of curried functions.
10249      *
10250      * @static
10251      * @memberOf _
10252      * @since 3.0.0
10253      * @category Function
10254      * @param {Function} func The function to curry.
10255      * @param {number} [arity=func.length] The arity of `func`.
10256      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
10257      * @returns {Function} Returns the new curried function.
10258      * @example
10259      *
10260      * var abc = function(a, b, c) {
10261      *   return [a, b, c];
10262      * };
10263      *
10264      * var curried = _.curryRight(abc);
10265      *
10266      * curried(3)(2)(1);
10267      * // => [1, 2, 3]
10268      *
10269      * curried(2, 3)(1);
10270      * // => [1, 2, 3]
10271      *
10272      * curried(1, 2, 3);
10273      * // => [1, 2, 3]
10274      *
10275      * // Curried with placeholders.
10276      * curried(3)(1, _)(2);
10277      * // => [1, 2, 3]
10278      */
10279     function curryRight(func, arity, guard) {
10280       arity = guard ? undefined : arity;
10281       var result = createWrap(func, WRAP_CURRY_RIGHT_FLAG, undefined, undefined, undefined, undefined, undefined, arity);
10282       result.placeholder = curryRight.placeholder;
10283       return result;
10284     }
10285
10286     /**
10287      * Creates a debounced function that delays invoking `func` until after `wait`
10288      * milliseconds have elapsed since the last time the debounced function was
10289      * invoked. The debounced function comes with a `cancel` method to cancel
10290      * delayed `func` invocations and a `flush` method to immediately invoke them.
10291      * Provide `options` to indicate whether `func` should be invoked on the
10292      * leading and/or trailing edge of the `wait` timeout. The `func` is invoked
10293      * with the last arguments provided to the debounced function. Subsequent
10294      * calls to the debounced function return the result of the last `func`
10295      * invocation.
10296      *
10297      * **Note:** If `leading` and `trailing` options are `true`, `func` is
10298      * invoked on the trailing edge of the timeout only if the debounced function
10299      * is invoked more than once during the `wait` timeout.
10300      *
10301      * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
10302      * until to the next tick, similar to `setTimeout` with a timeout of `0`.
10303      *
10304      * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
10305      * for details over the differences between `_.debounce` and `_.throttle`.
10306      *
10307      * @static
10308      * @memberOf _
10309      * @since 0.1.0
10310      * @category Function
10311      * @param {Function} func The function to debounce.
10312      * @param {number} [wait=0] The number of milliseconds to delay.
10313      * @param {Object} [options={}] The options object.
10314      * @param {boolean} [options.leading=false]
10315      *  Specify invoking on the leading edge of the timeout.
10316      * @param {number} [options.maxWait]
10317      *  The maximum time `func` is allowed to be delayed before it's invoked.
10318      * @param {boolean} [options.trailing=true]
10319      *  Specify invoking on the trailing edge of the timeout.
10320      * @returns {Function} Returns the new debounced function.
10321      * @example
10322      *
10323      * // Avoid costly calculations while the window size is in flux.
10324      * jQuery(window).on('resize', _.debounce(calculateLayout, 150));
10325      *
10326      * // Invoke `sendMail` when clicked, debouncing subsequent calls.
10327      * jQuery(element).on('click', _.debounce(sendMail, 300, {
10328      *   'leading': true,
10329      *   'trailing': false
10330      * }));
10331      *
10332      * // Ensure `batchLog` is invoked once after 1 second of debounced calls.
10333      * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });
10334      * var source = new EventSource('/stream');
10335      * jQuery(source).on('message', debounced);
10336      *
10337      * // Cancel the trailing debounced invocation.
10338      * jQuery(window).on('popstate', debounced.cancel);
10339      */
10340     function debounce(func, wait, options) {
10341       var lastArgs,
10342           lastThis,
10343           maxWait,
10344           result,
10345           timerId,
10346           lastCallTime,
10347           lastInvokeTime = 0,
10348           leading = false,
10349           maxing = false,
10350           trailing = true;
10351
10352       if (typeof func != 'function') {
10353         throw new TypeError(FUNC_ERROR_TEXT);
10354       }
10355       wait = toNumber(wait) || 0;
10356       if (isObject(options)) {
10357         leading = !!options.leading;
10358         maxing = 'maxWait' in options;
10359         maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;
10360         trailing = 'trailing' in options ? !!options.trailing : trailing;
10361       }
10362
10363       function invokeFunc(time) {
10364         var args = lastArgs,
10365             thisArg = lastThis;
10366
10367         lastArgs = lastThis = undefined;
10368         lastInvokeTime = time;
10369         result = func.apply(thisArg, args);
10370         return result;
10371       }
10372
10373       function leadingEdge(time) {
10374         // Reset any `maxWait` timer.
10375         lastInvokeTime = time;
10376         // Start the timer for the trailing edge.
10377         timerId = setTimeout(timerExpired, wait);
10378         // Invoke the leading edge.
10379         return leading ? invokeFunc(time) : result;
10380       }
10381
10382       function remainingWait(time) {
10383         var timeSinceLastCall = time - lastCallTime,
10384             timeSinceLastInvoke = time - lastInvokeTime,
10385             result = wait - timeSinceLastCall;
10386
10387         return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;
10388       }
10389
10390       function shouldInvoke(time) {
10391         var timeSinceLastCall = time - lastCallTime,
10392             timeSinceLastInvoke = time - lastInvokeTime;
10393
10394         // Either this is the first call, activity has stopped and we're at the
10395         // trailing edge, the system time has gone backwards and we're treating
10396         // it as the trailing edge, or we've hit the `maxWait` limit.
10397         return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||
10398           (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));
10399       }
10400
10401       function timerExpired() {
10402         var time = now();
10403         if (shouldInvoke(time)) {
10404           return trailingEdge(time);
10405         }
10406         // Restart the timer.
10407         timerId = setTimeout(timerExpired, remainingWait(time));
10408       }
10409
10410       function trailingEdge(time) {
10411         timerId = undefined;
10412
10413         // Only invoke if we have `lastArgs` which means `func` has been
10414         // debounced at least once.
10415         if (trailing && lastArgs) {
10416           return invokeFunc(time);
10417         }
10418         lastArgs = lastThis = undefined;
10419         return result;
10420       }
10421
10422       function cancel() {
10423         if (timerId !== undefined) {
10424           clearTimeout(timerId);
10425         }
10426         lastInvokeTime = 0;
10427         lastArgs = lastCallTime = lastThis = timerId = undefined;
10428       }
10429
10430       function flush() {
10431         return timerId === undefined ? result : trailingEdge(now());
10432       }
10433
10434       function debounced() {
10435         var time = now(),
10436             isInvoking = shouldInvoke(time);
10437
10438         lastArgs = arguments;
10439         lastThis = this;
10440         lastCallTime = time;
10441
10442         if (isInvoking) {
10443           if (timerId === undefined) {
10444             return leadingEdge(lastCallTime);
10445           }
10446           if (maxing) {
10447             // Handle invocations in a tight loop.
10448             timerId = setTimeout(timerExpired, wait);
10449             return invokeFunc(lastCallTime);
10450           }
10451         }
10452         if (timerId === undefined) {
10453           timerId = setTimeout(timerExpired, wait);
10454         }
10455         return result;
10456       }
10457       debounced.cancel = cancel;
10458       debounced.flush = flush;
10459       return debounced;
10460     }
10461
10462     /**
10463      * Defers invoking the `func` until the current call stack has cleared. Any
10464      * additional arguments are provided to `func` when it's invoked.
10465      *
10466      * @static
10467      * @memberOf _
10468      * @since 0.1.0
10469      * @category Function
10470      * @param {Function} func The function to defer.
10471      * @param {...*} [args] The arguments to invoke `func` with.
10472      * @returns {number} Returns the timer id.
10473      * @example
10474      *
10475      * _.defer(function(text) {
10476      *   console.log(text);
10477      * }, 'deferred');
10478      * // => Logs 'deferred' after one millisecond.
10479      */
10480     var defer = baseRest(function(func, args) {
10481       return baseDelay(func, 1, args);
10482     });
10483
10484     /**
10485      * Invokes `func` after `wait` milliseconds. Any additional arguments are
10486      * provided to `func` when it's invoked.
10487      *
10488      * @static
10489      * @memberOf _
10490      * @since 0.1.0
10491      * @category Function
10492      * @param {Function} func The function to delay.
10493      * @param {number} wait The number of milliseconds to delay invocation.
10494      * @param {...*} [args] The arguments to invoke `func` with.
10495      * @returns {number} Returns the timer id.
10496      * @example
10497      *
10498      * _.delay(function(text) {
10499      *   console.log(text);
10500      * }, 1000, 'later');
10501      * // => Logs 'later' after one second.
10502      */
10503     var delay = baseRest(function(func, wait, args) {
10504       return baseDelay(func, toNumber(wait) || 0, args);
10505     });
10506
10507     /**
10508      * Creates a function that invokes `func` with arguments reversed.
10509      *
10510      * @static
10511      * @memberOf _
10512      * @since 4.0.0
10513      * @category Function
10514      * @param {Function} func The function to flip arguments for.
10515      * @returns {Function} Returns the new flipped function.
10516      * @example
10517      *
10518      * var flipped = _.flip(function() {
10519      *   return _.toArray(arguments);
10520      * });
10521      *
10522      * flipped('a', 'b', 'c', 'd');
10523      * // => ['d', 'c', 'b', 'a']
10524      */
10525     function flip(func) {
10526       return createWrap(func, WRAP_FLIP_FLAG);
10527     }
10528
10529     /**
10530      * Creates a function that memoizes the result of `func`. If `resolver` is
10531      * provided, it determines the cache key for storing the result based on the
10532      * arguments provided to the memoized function. By default, the first argument
10533      * provided to the memoized function is used as the map cache key. The `func`
10534      * is invoked with the `this` binding of the memoized function.
10535      *
10536      * **Note:** The cache is exposed as the `cache` property on the memoized
10537      * function. Its creation may be customized by replacing the `_.memoize.Cache`
10538      * constructor with one whose instances implement the
10539      * [`Map`](http://ecma-international.org/ecma-262/7.0/#sec-properties-of-the-map-prototype-object)
10540      * method interface of `clear`, `delete`, `get`, `has`, and `set`.
10541      *
10542      * @static
10543      * @memberOf _
10544      * @since 0.1.0
10545      * @category Function
10546      * @param {Function} func The function to have its output memoized.
10547      * @param {Function} [resolver] The function to resolve the cache key.
10548      * @returns {Function} Returns the new memoized function.
10549      * @example
10550      *
10551      * var object = { 'a': 1, 'b': 2 };
10552      * var other = { 'c': 3, 'd': 4 };
10553      *
10554      * var values = _.memoize(_.values);
10555      * values(object);
10556      * // => [1, 2]
10557      *
10558      * values(other);
10559      * // => [3, 4]
10560      *
10561      * object.a = 2;
10562      * values(object);
10563      * // => [1, 2]
10564      *
10565      * // Modify the result cache.
10566      * values.cache.set(object, ['a', 'b']);
10567      * values(object);
10568      * // => ['a', 'b']
10569      *
10570      * // Replace `_.memoize.Cache`.
10571      * _.memoize.Cache = WeakMap;
10572      */
10573     function memoize(func, resolver) {
10574       if (typeof func != 'function' || (resolver != null && typeof resolver != 'function')) {
10575         throw new TypeError(FUNC_ERROR_TEXT);
10576       }
10577       var memoized = function() {
10578         var args = arguments,
10579             key = resolver ? resolver.apply(this, args) : args[0],
10580             cache = memoized.cache;
10581
10582         if (cache.has(key)) {
10583           return cache.get(key);
10584         }
10585         var result = func.apply(this, args);
10586         memoized.cache = cache.set(key, result) || cache;
10587         return result;
10588       };
10589       memoized.cache = new (memoize.Cache || MapCache);
10590       return memoized;
10591     }
10592
10593     // Expose `MapCache`.
10594     memoize.Cache = MapCache;
10595
10596     /**
10597      * Creates a function that negates the result of the predicate `func`. The
10598      * `func` predicate is invoked with the `this` binding and arguments of the
10599      * created function.
10600      *
10601      * @static
10602      * @memberOf _
10603      * @since 3.0.0
10604      * @category Function
10605      * @param {Function} predicate The predicate to negate.
10606      * @returns {Function} Returns the new negated function.
10607      * @example
10608      *
10609      * function isEven(n) {
10610      *   return n % 2 == 0;
10611      * }
10612      *
10613      * _.filter([1, 2, 3, 4, 5, 6], _.negate(isEven));
10614      * // => [1, 3, 5]
10615      */
10616     function negate(predicate) {
10617       if (typeof predicate != 'function') {
10618         throw new TypeError(FUNC_ERROR_TEXT);
10619       }
10620       return function() {
10621         var args = arguments;
10622         switch (args.length) {
10623           case 0: return !predicate.call(this);
10624           case 1: return !predicate.call(this, args[0]);
10625           case 2: return !predicate.call(this, args[0], args[1]);
10626           case 3: return !predicate.call(this, args[0], args[1], args[2]);
10627         }
10628         return !predicate.apply(this, args);
10629       };
10630     }
10631
10632     /**
10633      * Creates a function that is restricted to invoking `func` once. Repeat calls
10634      * to the function return the value of the first invocation. The `func` is
10635      * invoked with the `this` binding and arguments of the created function.
10636      *
10637      * @static
10638      * @memberOf _
10639      * @since 0.1.0
10640      * @category Function
10641      * @param {Function} func The function to restrict.
10642      * @returns {Function} Returns the new restricted function.
10643      * @example
10644      *
10645      * var initialize = _.once(createApplication);
10646      * initialize();
10647      * initialize();
10648      * // => `createApplication` is invoked once
10649      */
10650     function once(func) {
10651       return before(2, func);
10652     }
10653
10654     /**
10655      * Creates a function that invokes `func` with its arguments transformed.
10656      *
10657      * @static
10658      * @since 4.0.0
10659      * @memberOf _
10660      * @category Function
10661      * @param {Function} func The function to wrap.
10662      * @param {...(Function|Function[])} [transforms=[_.identity]]
10663      *  The argument transforms.
10664      * @returns {Function} Returns the new function.
10665      * @example
10666      *
10667      * function doubled(n) {
10668      *   return n * 2;
10669      * }
10670      *
10671      * function square(n) {
10672      *   return n * n;
10673      * }
10674      *
10675      * var func = _.overArgs(function(x, y) {
10676      *   return [x, y];
10677      * }, [square, doubled]);
10678      *
10679      * func(9, 3);
10680      * // => [81, 6]
10681      *
10682      * func(10, 5);
10683      * // => [100, 10]
10684      */
10685     var overArgs = castRest(function(func, transforms) {
10686       transforms = (transforms.length == 1 && isArray(transforms[0]))
10687         ? arrayMap(transforms[0], baseUnary(getIteratee()))
10688         : arrayMap(baseFlatten(transforms, 1), baseUnary(getIteratee()));
10689
10690       var funcsLength = transforms.length;
10691       return baseRest(function(args) {
10692         var index = -1,
10693             length = nativeMin(args.length, funcsLength);
10694
10695         while (++index < length) {
10696           args[index] = transforms[index].call(this, args[index]);
10697         }
10698         return apply(func, this, args);
10699       });
10700     });
10701
10702     /**
10703      * Creates a function that invokes `func` with `partials` prepended to the
10704      * arguments it receives. This method is like `_.bind` except it does **not**
10705      * alter the `this` binding.
10706      *
10707      * The `_.partial.placeholder` value, which defaults to `_` in monolithic
10708      * builds, may be used as a placeholder for partially applied arguments.
10709      *
10710      * **Note:** This method doesn't set the "length" property of partially
10711      * applied functions.
10712      *
10713      * @static
10714      * @memberOf _
10715      * @since 0.2.0
10716      * @category Function
10717      * @param {Function} func The function to partially apply arguments to.
10718      * @param {...*} [partials] The arguments to be partially applied.
10719      * @returns {Function} Returns the new partially applied function.
10720      * @example
10721      *
10722      * function greet(greeting, name) {
10723      *   return greeting + ' ' + name;
10724      * }
10725      *
10726      * var sayHelloTo = _.partial(greet, 'hello');
10727      * sayHelloTo('fred');
10728      * // => 'hello fred'
10729      *
10730      * // Partially applied with placeholders.
10731      * var greetFred = _.partial(greet, _, 'fred');
10732      * greetFred('hi');
10733      * // => 'hi fred'
10734      */
10735     var partial = baseRest(function(func, partials) {
10736       var holders = replaceHolders(partials, getHolder(partial));
10737       return createWrap(func, WRAP_PARTIAL_FLAG, undefined, partials, holders);
10738     });
10739
10740     /**
10741      * This method is like `_.partial` except that partially applied arguments
10742      * are appended to the arguments it receives.
10743      *
10744      * The `_.partialRight.placeholder` value, which defaults to `_` in monolithic
10745      * builds, may be used as a placeholder for partially applied arguments.
10746      *
10747      * **Note:** This method doesn't set the "length" property of partially
10748      * applied functions.
10749      *
10750      * @static
10751      * @memberOf _
10752      * @since 1.0.0
10753      * @category Function
10754      * @param {Function} func The function to partially apply arguments to.
10755      * @param {...*} [partials] The arguments to be partially applied.
10756      * @returns {Function} Returns the new partially applied function.
10757      * @example
10758      *
10759      * function greet(greeting, name) {
10760      *   return greeting + ' ' + name;
10761      * }
10762      *
10763      * var greetFred = _.partialRight(greet, 'fred');
10764      * greetFred('hi');
10765      * // => 'hi fred'
10766      *
10767      * // Partially applied with placeholders.
10768      * var sayHelloTo = _.partialRight(greet, 'hello', _);
10769      * sayHelloTo('fred');
10770      * // => 'hello fred'
10771      */
10772     var partialRight = baseRest(function(func, partials) {
10773       var holders = replaceHolders(partials, getHolder(partialRight));
10774       return createWrap(func, WRAP_PARTIAL_RIGHT_FLAG, undefined, partials, holders);
10775     });
10776
10777     /**
10778      * Creates a function that invokes `func` with arguments arranged according
10779      * to the specified `indexes` where the argument value at the first index is
10780      * provided as the first argument, the argument value at the second index is
10781      * provided as the second argument, and so on.
10782      *
10783      * @static
10784      * @memberOf _
10785      * @since 3.0.0
10786      * @category Function
10787      * @param {Function} func The function to rearrange arguments for.
10788      * @param {...(number|number[])} indexes The arranged argument indexes.
10789      * @returns {Function} Returns the new function.
10790      * @example
10791      *
10792      * var rearged = _.rearg(function(a, b, c) {
10793      *   return [a, b, c];
10794      * }, [2, 0, 1]);
10795      *
10796      * rearged('b', 'c', 'a')
10797      * // => ['a', 'b', 'c']
10798      */
10799     var rearg = flatRest(function(func, indexes) {
10800       return createWrap(func, WRAP_REARG_FLAG, undefined, undefined, undefined, indexes);
10801     });
10802
10803     /**
10804      * Creates a function that invokes `func` with the `this` binding of the
10805      * created function and arguments from `start` and beyond provided as
10806      * an array.
10807      *
10808      * **Note:** This method is based on the
10809      * [rest parameter](https://mdn.io/rest_parameters).
10810      *
10811      * @static
10812      * @memberOf _
10813      * @since 4.0.0
10814      * @category Function
10815      * @param {Function} func The function to apply a rest parameter to.
10816      * @param {number} [start=func.length-1] The start position of the rest parameter.
10817      * @returns {Function} Returns the new function.
10818      * @example
10819      *
10820      * var say = _.rest(function(what, names) {
10821      *   return what + ' ' + _.initial(names).join(', ') +
10822      *     (_.size(names) > 1 ? ', & ' : '') + _.last(names);
10823      * });
10824      *
10825      * say('hello', 'fred', 'barney', 'pebbles');
10826      * // => 'hello fred, barney, & pebbles'
10827      */
10828     function rest(func, start) {
10829       if (typeof func != 'function') {
10830         throw new TypeError(FUNC_ERROR_TEXT);
10831       }
10832       start = start === undefined ? start : toInteger(start);
10833       return baseRest(func, start);
10834     }
10835
10836     /**
10837      * Creates a function that invokes `func` with the `this` binding of the
10838      * create function and an array of arguments much like
10839      * [`Function#apply`](http://www.ecma-international.org/ecma-262/7.0/#sec-function.prototype.apply).
10840      *
10841      * **Note:** This method is based on the
10842      * [spread operator](https://mdn.io/spread_operator).
10843      *
10844      * @static
10845      * @memberOf _
10846      * @since 3.2.0
10847      * @category Function
10848      * @param {Function} func The function to spread arguments over.
10849      * @param {number} [start=0] The start position of the spread.
10850      * @returns {Function} Returns the new function.
10851      * @example
10852      *
10853      * var say = _.spread(function(who, what) {
10854      *   return who + ' says ' + what;
10855      * });
10856      *
10857      * say(['fred', 'hello']);
10858      * // => 'fred says hello'
10859      *
10860      * var numbers = Promise.all([
10861      *   Promise.resolve(40),
10862      *   Promise.resolve(36)
10863      * ]);
10864      *
10865      * numbers.then(_.spread(function(x, y) {
10866      *   return x + y;
10867      * }));
10868      * // => a Promise of 76
10869      */
10870     function spread(func, start) {
10871       if (typeof func != 'function') {
10872         throw new TypeError(FUNC_ERROR_TEXT);
10873       }
10874       start = start === undefined ? 0 : nativeMax(toInteger(start), 0);
10875       return baseRest(function(args) {
10876         var array = args[start],
10877             lastIndex = args.length - 1,
10878             otherArgs = castSlice(args, 0, start);
10879
10880         if (array) {
10881           arrayPush(otherArgs, array);
10882         }
10883         if (start != lastIndex) {
10884           arrayPush(otherArgs, castSlice(args, start + 1));
10885         }
10886         return apply(func, this, otherArgs);
10887       });
10888     }
10889
10890     /**
10891      * Creates a throttled function that only invokes `func` at most once per
10892      * every `wait` milliseconds. The throttled function comes with a `cancel`
10893      * method to cancel delayed `func` invocations and a `flush` method to
10894      * immediately invoke them. Provide `options` to indicate whether `func`
10895      * should be invoked on the leading and/or trailing edge of the `wait`
10896      * timeout. The `func` is invoked with the last arguments provided to the
10897      * throttled function. Subsequent calls to the throttled function return the
10898      * result of the last `func` invocation.
10899      *
10900      * **Note:** If `leading` and `trailing` options are `true`, `func` is
10901      * invoked on the trailing edge of the timeout only if the throttled function
10902      * is invoked more than once during the `wait` timeout.
10903      *
10904      * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred
10905      * until to the next tick, similar to `setTimeout` with a timeout of `0`.
10906      *
10907      * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)
10908      * for details over the differences between `_.throttle` and `_.debounce`.
10909      *
10910      * @static
10911      * @memberOf _
10912      * @since 0.1.0
10913      * @category Function
10914      * @param {Function} func The function to throttle.
10915      * @param {number} [wait=0] The number of milliseconds to throttle invocations to.
10916      * @param {Object} [options={}] The options object.
10917      * @param {boolean} [options.leading=true]
10918      *  Specify invoking on the leading edge of the timeout.
10919      * @param {boolean} [options.trailing=true]
10920      *  Specify invoking on the trailing edge of the timeout.
10921      * @returns {Function} Returns the new throttled function.
10922      * @example
10923      *
10924      * // Avoid excessively updating the position while scrolling.
10925      * jQuery(window).on('scroll', _.throttle(updatePosition, 100));
10926      *
10927      * // Invoke `renewToken` when the click event is fired, but not more than once every 5 minutes.
10928      * var throttled = _.throttle(renewToken, 300000, { 'trailing': false });
10929      * jQuery(element).on('click', throttled);
10930      *
10931      * // Cancel the trailing throttled invocation.
10932      * jQuery(window).on('popstate', throttled.cancel);
10933      */
10934     function throttle(func, wait, options) {
10935       var leading = true,
10936           trailing = true;
10937
10938       if (typeof func != 'function') {
10939         throw new TypeError(FUNC_ERROR_TEXT);
10940       }
10941       if (isObject(options)) {
10942         leading = 'leading' in options ? !!options.leading : leading;
10943         trailing = 'trailing' in options ? !!options.trailing : trailing;
10944       }
10945       return debounce(func, wait, {
10946         'leading': leading,
10947         'maxWait': wait,
10948         'trailing': trailing
10949       });
10950     }
10951
10952     /**
10953      * Creates a function that accepts up to one argument, ignoring any
10954      * additional arguments.
10955      *
10956      * @static
10957      * @memberOf _
10958      * @since 4.0.0
10959      * @category Function
10960      * @param {Function} func The function to cap arguments for.
10961      * @returns {Function} Returns the new capped function.
10962      * @example
10963      *
10964      * _.map(['6', '8', '10'], _.unary(parseInt));
10965      * // => [6, 8, 10]
10966      */
10967     function unary(func) {
10968       return ary(func, 1);
10969     }
10970
10971     /**
10972      * Creates a function that provides `value` to `wrapper` as its first
10973      * argument. Any additional arguments provided to the function are appended
10974      * to those provided to the `wrapper`. The wrapper is invoked with the `this`
10975      * binding of the created function.
10976      *
10977      * @static
10978      * @memberOf _
10979      * @since 0.1.0
10980      * @category Function
10981      * @param {*} value The value to wrap.
10982      * @param {Function} [wrapper=identity] The wrapper function.
10983      * @returns {Function} Returns the new function.
10984      * @example
10985      *
10986      * var p = _.wrap(_.escape, function(func, text) {
10987      *   return '<p>' + func(text) + '</p>';
10988      * });
10989      *
10990      * p('fred, barney, & pebbles');
10991      * // => '<p>fred, barney, &amp; pebbles</p>'
10992      */
10993     function wrap(value, wrapper) {
10994       return partial(castFunction(wrapper), value);
10995     }
10996
10997     /*------------------------------------------------------------------------*/
10998
10999     /**
11000      * Casts `value` as an array if it's not one.
11001      *
11002      * @static
11003      * @memberOf _
11004      * @since 4.4.0
11005      * @category Lang
11006      * @param {*} value The value to inspect.
11007      * @returns {Array} Returns the cast array.
11008      * @example
11009      *
11010      * _.castArray(1);
11011      * // => [1]
11012      *
11013      * _.castArray({ 'a': 1 });
11014      * // => [{ 'a': 1 }]
11015      *
11016      * _.castArray('abc');
11017      * // => ['abc']
11018      *
11019      * _.castArray(null);
11020      * // => [null]
11021      *
11022      * _.castArray(undefined);
11023      * // => [undefined]
11024      *
11025      * _.castArray();
11026      * // => []
11027      *
11028      * var array = [1, 2, 3];
11029      * console.log(_.castArray(array) === array);
11030      * // => true
11031      */
11032     function castArray() {
11033       if (!arguments.length) {
11034         return [];
11035       }
11036       var value = arguments[0];
11037       return isArray(value) ? value : [value];
11038     }
11039
11040     /**
11041      * Creates a shallow clone of `value`.
11042      *
11043      * **Note:** This method is loosely based on the
11044      * [structured clone algorithm](https://mdn.io/Structured_clone_algorithm)
11045      * and supports cloning arrays, array buffers, booleans, date objects, maps,
11046      * numbers, `Object` objects, regexes, sets, strings, symbols, and typed
11047      * arrays. The own enumerable properties of `arguments` objects are cloned
11048      * as plain objects. An empty object is returned for uncloneable values such
11049      * as error objects, functions, DOM nodes, and WeakMaps.
11050      *
11051      * @static
11052      * @memberOf _
11053      * @since 0.1.0
11054      * @category Lang
11055      * @param {*} value The value to clone.
11056      * @returns {*} Returns the cloned value.
11057      * @see _.cloneDeep
11058      * @example
11059      *
11060      * var objects = [{ 'a': 1 }, { 'b': 2 }];
11061      *
11062      * var shallow = _.clone(objects);
11063      * console.log(shallow[0] === objects[0]);
11064      * // => true
11065      */
11066     function clone(value) {
11067       return baseClone(value, CLONE_SYMBOLS_FLAG);
11068     }
11069
11070     /**
11071      * This method is like `_.clone` except that it accepts `customizer` which
11072      * is invoked to produce the cloned value. If `customizer` returns `undefined`,
11073      * cloning is handled by the method instead. The `customizer` is invoked with
11074      * up to four arguments; (value [, index|key, object, stack]).
11075      *
11076      * @static
11077      * @memberOf _
11078      * @since 4.0.0
11079      * @category Lang
11080      * @param {*} value The value to clone.
11081      * @param {Function} [customizer] The function to customize cloning.
11082      * @returns {*} Returns the cloned value.
11083      * @see _.cloneDeepWith
11084      * @example
11085      *
11086      * function customizer(value) {
11087      *   if (_.isElement(value)) {
11088      *     return value.cloneNode(false);
11089      *   }
11090      * }
11091      *
11092      * var el = _.cloneWith(document.body, customizer);
11093      *
11094      * console.log(el === document.body);
11095      * // => false
11096      * console.log(el.nodeName);
11097      * // => 'BODY'
11098      * console.log(el.childNodes.length);
11099      * // => 0
11100      */
11101     function cloneWith(value, customizer) {
11102       customizer = typeof customizer == 'function' ? customizer : undefined;
11103       return baseClone(value, CLONE_SYMBOLS_FLAG, customizer);
11104     }
11105
11106     /**
11107      * This method is like `_.clone` except that it recursively clones `value`.
11108      *
11109      * @static
11110      * @memberOf _
11111      * @since 1.0.0
11112      * @category Lang
11113      * @param {*} value The value to recursively clone.
11114      * @returns {*} Returns the deep cloned value.
11115      * @see _.clone
11116      * @example
11117      *
11118      * var objects = [{ 'a': 1 }, { 'b': 2 }];
11119      *
11120      * var deep = _.cloneDeep(objects);
11121      * console.log(deep[0] === objects[0]);
11122      * // => false
11123      */
11124     function cloneDeep(value) {
11125       return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG);
11126     }
11127
11128     /**
11129      * This method is like `_.cloneWith` except that it recursively clones `value`.
11130      *
11131      * @static
11132      * @memberOf _
11133      * @since 4.0.0
11134      * @category Lang
11135      * @param {*} value The value to recursively clone.
11136      * @param {Function} [customizer] The function to customize cloning.
11137      * @returns {*} Returns the deep cloned value.
11138      * @see _.cloneWith
11139      * @example
11140      *
11141      * function customizer(value) {
11142      *   if (_.isElement(value)) {
11143      *     return value.cloneNode(true);
11144      *   }
11145      * }
11146      *
11147      * var el = _.cloneDeepWith(document.body, customizer);
11148      *
11149      * console.log(el === document.body);
11150      * // => false
11151      * console.log(el.nodeName);
11152      * // => 'BODY'
11153      * console.log(el.childNodes.length);
11154      * // => 20
11155      */
11156     function cloneDeepWith(value, customizer) {
11157       customizer = typeof customizer == 'function' ? customizer : undefined;
11158       return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG, customizer);
11159     }
11160
11161     /**
11162      * Checks if `object` conforms to `source` by invoking the predicate
11163      * properties of `source` with the corresponding property values of `object`.
11164      *
11165      * **Note:** This method is equivalent to `_.conforms` when `source` is
11166      * partially applied.
11167      *
11168      * @static
11169      * @memberOf _
11170      * @since 4.14.0
11171      * @category Lang
11172      * @param {Object} object The object to inspect.
11173      * @param {Object} source The object of property predicates to conform to.
11174      * @returns {boolean} Returns `true` if `object` conforms, else `false`.
11175      * @example
11176      *
11177      * var object = { 'a': 1, 'b': 2 };
11178      *
11179      * _.conformsTo(object, { 'b': function(n) { return n > 1; } });
11180      * // => true
11181      *
11182      * _.conformsTo(object, { 'b': function(n) { return n > 2; } });
11183      * // => false
11184      */
11185     function conformsTo(object, source) {
11186       return source == null || baseConformsTo(object, source, keys(source));
11187     }
11188
11189     /**
11190      * Performs a
11191      * [`SameValueZero`](http://ecma-international.org/ecma-262/7.0/#sec-samevaluezero)
11192      * comparison between two values to determine if they are equivalent.
11193      *
11194      * @static
11195      * @memberOf _
11196      * @since 4.0.0
11197      * @category Lang
11198      * @param {*} value The value to compare.
11199      * @param {*} other The other value to compare.
11200      * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
11201      * @example
11202      *
11203      * var object = { 'a': 1 };
11204      * var other = { 'a': 1 };
11205      *
11206      * _.eq(object, object);
11207      * // => true
11208      *
11209      * _.eq(object, other);
11210      * // => false
11211      *
11212      * _.eq('a', 'a');
11213      * // => true
11214      *
11215      * _.eq('a', Object('a'));
11216      * // => false
11217      *
11218      * _.eq(NaN, NaN);
11219      * // => true
11220      */
11221     function eq(value, other) {
11222       return value === other || (value !== value && other !== other);
11223     }
11224
11225     /**
11226      * Checks if `value` is greater than `other`.
11227      *
11228      * @static
11229      * @memberOf _
11230      * @since 3.9.0
11231      * @category Lang
11232      * @param {*} value The value to compare.
11233      * @param {*} other The other value to compare.
11234      * @returns {boolean} Returns `true` if `value` is greater than `other`,
11235      *  else `false`.
11236      * @see _.lt
11237      * @example
11238      *
11239      * _.gt(3, 1);
11240      * // => true
11241      *
11242      * _.gt(3, 3);
11243      * // => false
11244      *
11245      * _.gt(1, 3);
11246      * // => false
11247      */
11248     var gt = createRelationalOperation(baseGt);
11249
11250     /**
11251      * Checks if `value` is greater than or equal to `other`.
11252      *
11253      * @static
11254      * @memberOf _
11255      * @since 3.9.0
11256      * @category Lang
11257      * @param {*} value The value to compare.
11258      * @param {*} other The other value to compare.
11259      * @returns {boolean} Returns `true` if `value` is greater than or equal to
11260      *  `other`, else `false`.
11261      * @see _.lte
11262      * @example
11263      *
11264      * _.gte(3, 1);
11265      * // => true
11266      *
11267      * _.gte(3, 3);
11268      * // => true
11269      *
11270      * _.gte(1, 3);
11271      * // => false
11272      */
11273     var gte = createRelationalOperation(function(value, other) {
11274       return value >= other;
11275     });
11276
11277     /**
11278      * Checks if `value` is likely an `arguments` object.
11279      *
11280      * @static
11281      * @memberOf _
11282      * @since 0.1.0
11283      * @category Lang
11284      * @param {*} value The value to check.
11285      * @returns {boolean} Returns `true` if `value` is an `arguments` object,
11286      *  else `false`.
11287      * @example
11288      *
11289      * _.isArguments(function() { return arguments; }());
11290      * // => true
11291      *
11292      * _.isArguments([1, 2, 3]);
11293      * // => false
11294      */
11295     var isArguments = baseIsArguments(function() { return arguments; }()) ? baseIsArguments : function(value) {
11296       return isObjectLike(value) && hasOwnProperty.call(value, 'callee') &&
11297         !propertyIsEnumerable.call(value, 'callee');
11298     };
11299
11300     /**
11301      * Checks if `value` is classified as an `Array` object.
11302      *
11303      * @static
11304      * @memberOf _
11305      * @since 0.1.0
11306      * @category Lang
11307      * @param {*} value The value to check.
11308      * @returns {boolean} Returns `true` if `value` is an array, else `false`.
11309      * @example
11310      *
11311      * _.isArray([1, 2, 3]);
11312      * // => true
11313      *
11314      * _.isArray(document.body.children);
11315      * // => false
11316      *
11317      * _.isArray('abc');
11318      * // => false
11319      *
11320      * _.isArray(_.noop);
11321      * // => false
11322      */
11323     var isArray = Array.isArray;
11324
11325     /**
11326      * Checks if `value` is classified as an `ArrayBuffer` object.
11327      *
11328      * @static
11329      * @memberOf _
11330      * @since 4.3.0
11331      * @category Lang
11332      * @param {*} value The value to check.
11333      * @returns {boolean} Returns `true` if `value` is an array buffer, else `false`.
11334      * @example
11335      *
11336      * _.isArrayBuffer(new ArrayBuffer(2));
11337      * // => true
11338      *
11339      * _.isArrayBuffer(new Array(2));
11340      * // => false
11341      */
11342     var isArrayBuffer = nodeIsArrayBuffer ? baseUnary(nodeIsArrayBuffer) : baseIsArrayBuffer;
11343
11344     /**
11345      * Checks if `value` is array-like. A value is considered array-like if it's
11346      * not a function and has a `value.length` that's an integer greater than or
11347      * equal to `0` and less than or equal to `Number.MAX_SAFE_INTEGER`.
11348      *
11349      * @static
11350      * @memberOf _
11351      * @since 4.0.0
11352      * @category Lang
11353      * @param {*} value The value to check.
11354      * @returns {boolean} Returns `true` if `value` is array-like, else `false`.
11355      * @example
11356      *
11357      * _.isArrayLike([1, 2, 3]);
11358      * // => true
11359      *
11360      * _.isArrayLike(document.body.children);
11361      * // => true
11362      *
11363      * _.isArrayLike('abc');
11364      * // => true
11365      *
11366      * _.isArrayLike(_.noop);
11367      * // => false
11368      */
11369     function isArrayLike(value) {
11370       return value != null && isLength(value.length) && !isFunction(value);
11371     }
11372
11373     /**
11374      * This method is like `_.isArrayLike` except that it also checks if `value`
11375      * is an object.
11376      *
11377      * @static
11378      * @memberOf _
11379      * @since 4.0.0
11380      * @category Lang
11381      * @param {*} value The value to check.
11382      * @returns {boolean} Returns `true` if `value` is an array-like object,
11383      *  else `false`.
11384      * @example
11385      *
11386      * _.isArrayLikeObject([1, 2, 3]);
11387      * // => true
11388      *
11389      * _.isArrayLikeObject(document.body.children);
11390      * // => true
11391      *
11392      * _.isArrayLikeObject('abc');
11393      * // => false
11394      *
11395      * _.isArrayLikeObject(_.noop);
11396      * // => false
11397      */
11398     function isArrayLikeObject(value) {
11399       return isObjectLike(value) && isArrayLike(value);
11400     }
11401
11402     /**
11403      * Checks if `value` is classified as a boolean primitive or object.
11404      *
11405      * @static
11406      * @memberOf _
11407      * @since 0.1.0
11408      * @category Lang
11409      * @param {*} value The value to check.
11410      * @returns {boolean} Returns `true` if `value` is a boolean, else `false`.
11411      * @example
11412      *
11413      * _.isBoolean(false);
11414      * // => true
11415      *
11416      * _.isBoolean(null);
11417      * // => false
11418      */
11419     function isBoolean(value) {
11420       return value === true || value === false ||
11421         (isObjectLike(value) && baseGetTag(value) == boolTag);
11422     }
11423
11424     /**
11425      * Checks if `value` is a buffer.
11426      *
11427      * @static
11428      * @memberOf _
11429      * @since 4.3.0
11430      * @category Lang
11431      * @param {*} value The value to check.
11432      * @returns {boolean} Returns `true` if `value` is a buffer, else `false`.
11433      * @example
11434      *
11435      * _.isBuffer(new Buffer(2));
11436      * // => true
11437      *
11438      * _.isBuffer(new Uint8Array(2));
11439      * // => false
11440      */
11441     var isBuffer = nativeIsBuffer || stubFalse;
11442
11443     /**
11444      * Checks if `value` is classified as a `Date` object.
11445      *
11446      * @static
11447      * @memberOf _
11448      * @since 0.1.0
11449      * @category Lang
11450      * @param {*} value The value to check.
11451      * @returns {boolean} Returns `true` if `value` is a date object, else `false`.
11452      * @example
11453      *
11454      * _.isDate(new Date);
11455      * // => true
11456      *
11457      * _.isDate('Mon April 23 2012');
11458      * // => false
11459      */
11460     var isDate = nodeIsDate ? baseUnary(nodeIsDate) : baseIsDate;
11461
11462     /**
11463      * Checks if `value` is likely a DOM element.
11464      *
11465      * @static
11466      * @memberOf _
11467      * @since 0.1.0
11468      * @category Lang
11469      * @param {*} value The value to check.
11470      * @returns {boolean} Returns `true` if `value` is a DOM element, else `false`.
11471      * @example
11472      *
11473      * _.isElement(document.body);
11474      * // => true
11475      *
11476      * _.isElement('<body>');
11477      * // => false
11478      */
11479     function isElement(value) {
11480       return isObjectLike(value) && value.nodeType === 1 && !isPlainObject(value);
11481     }
11482
11483     /**
11484      * Checks if `value` is an empty object, collection, map, or set.
11485      *
11486      * Objects are considered empty if they have no own enumerable string keyed
11487      * properties.
11488      *
11489      * Array-like values such as `arguments` objects, arrays, buffers, strings, or
11490      * jQuery-like collections are considered empty if they have a `length` of `0`.
11491      * Similarly, maps and sets are considered empty if they have a `size` of `0`.
11492      *
11493      * @static
11494      * @memberOf _
11495      * @since 0.1.0
11496      * @category Lang
11497      * @param {*} value The value to check.
11498      * @returns {boolean} Returns `true` if `value` is empty, else `false`.
11499      * @example
11500      *
11501      * _.isEmpty(null);
11502      * // => true
11503      *
11504      * _.isEmpty(true);
11505      * // => true
11506      *
11507      * _.isEmpty(1);
11508      * // => true
11509      *
11510      * _.isEmpty([1, 2, 3]);
11511      * // => false
11512      *
11513      * _.isEmpty({ 'a': 1 });
11514      * // => false
11515      */
11516     function isEmpty(value) {
11517       if (value == null) {
11518         return true;
11519       }
11520       if (isArrayLike(value) &&
11521           (isArray(value) || typeof value == 'string' || typeof value.splice == 'function' ||
11522             isBuffer(value) || isTypedArray(value) || isArguments(value))) {
11523         return !value.length;
11524       }
11525       var tag = getTag(value);
11526       if (tag == mapTag || tag == setTag) {
11527         return !value.size;
11528       }
11529       if (isPrototype(value)) {
11530         return !baseKeys(value).length;
11531       }
11532       for (var key in value) {
11533         if (hasOwnProperty.call(value, key)) {
11534           return false;
11535         }
11536       }
11537       return true;
11538     }
11539
11540     /**
11541      * Performs a deep comparison between two values to determine if they are
11542      * equivalent.
11543      *
11544      * **Note:** This method supports comparing arrays, array buffers, booleans,
11545      * date objects, error objects, maps, numbers, `Object` objects, regexes,
11546      * sets, strings, symbols, and typed arrays. `Object` objects are compared
11547      * by their own, not inherited, enumerable properties. Functions and DOM
11548      * nodes are **not** supported.
11549      *
11550      * @static
11551      * @memberOf _
11552      * @since 0.1.0
11553      * @category Lang
11554      * @param {*} value The value to compare.
11555      * @param {*} other The other value to compare.
11556      * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
11557      * @example
11558      *
11559      * var object = { 'a': 1 };
11560      * var other = { 'a': 1 };
11561      *
11562      * _.isEqual(object, other);
11563      * // => true
11564      *
11565      * object === other;
11566      * // => false
11567      */
11568     function isEqual(value, other) {
11569       return baseIsEqual(value, other);
11570     }
11571
11572     /**
11573      * This method is like `_.isEqual` except that it accepts `customizer` which
11574      * is invoked to compare values. If `customizer` returns `undefined`, comparisons
11575      * are handled by the method instead. The `customizer` is invoked with up to
11576      * six arguments: (objValue, othValue [, index|key, object, other, stack]).
11577      *
11578      * @static
11579      * @memberOf _
11580      * @since 4.0.0
11581      * @category Lang
11582      * @param {*} value The value to compare.
11583      * @param {*} other The other value to compare.
11584      * @param {Function} [customizer] The function to customize comparisons.
11585      * @returns {boolean} Returns `true` if the values are equivalent, else `false`.
11586      * @example
11587      *
11588      * function isGreeting(value) {
11589      *   return /^h(?:i|ello)$/.test(value);
11590      * }
11591      *
11592      * function customizer(objValue, othValue) {
11593      *   if (isGreeting(objValue) && isGreeting(othValue)) {
11594      *     return true;
11595      *   }
11596      * }
11597      *
11598      * var array = ['hello', 'goodbye'];
11599      * var other = ['hi', 'goodbye'];
11600      *
11601      * _.isEqualWith(array, other, customizer);
11602      * // => true
11603      */
11604     function isEqualWith(value, other, customizer) {
11605       customizer = typeof customizer == 'function' ? customizer : undefined;
11606       var result = customizer ? customizer(value, other) : undefined;
11607       return result === undefined ? baseIsEqual(value, other, undefined, customizer) : !!result;
11608     }
11609
11610     /**
11611      * Checks if `value` is an `Error`, `EvalError`, `RangeError`, `ReferenceError`,
11612      * `SyntaxError`, `TypeError`, or `URIError` object.
11613      *
11614      * @static
11615      * @memberOf _
11616      * @since 3.0.0
11617      * @category Lang
11618      * @param {*} value The value to check.
11619      * @returns {boolean} Returns `true` if `value` is an error object, else `false`.
11620      * @example
11621      *
11622      * _.isError(new Error);
11623      * // => true
11624      *
11625      * _.isError(Error);
11626      * // => false
11627      */
11628     function isError(value) {
11629       if (!isObjectLike(value)) {
11630         return false;
11631       }
11632       var tag = baseGetTag(value);
11633       return tag == errorTag || tag == domExcTag ||
11634         (typeof value.message == 'string' && typeof value.name == 'string' && !isPlainObject(value));
11635     }
11636
11637     /**
11638      * Checks if `value` is a finite primitive number.
11639      *
11640      * **Note:** This method is based on
11641      * [`Number.isFinite`](https://mdn.io/Number/isFinite).
11642      *
11643      * @static
11644      * @memberOf _
11645      * @since 0.1.0
11646      * @category Lang
11647      * @param {*} value The value to check.
11648      * @returns {boolean} Returns `true` if `value` is a finite number, else `false`.
11649      * @example
11650      *
11651      * _.isFinite(3);
11652      * // => true
11653      *
11654      * _.isFinite(Number.MIN_VALUE);
11655      * // => true
11656      *
11657      * _.isFinite(Infinity);
11658      * // => false
11659      *
11660      * _.isFinite('3');
11661      * // => false
11662      */
11663     function isFinite(value) {
11664       return typeof value == 'number' && nativeIsFinite(value);
11665     }
11666
11667     /**
11668      * Checks if `value` is classified as a `Function` object.
11669      *
11670      * @static
11671      * @memberOf _
11672      * @since 0.1.0
11673      * @category Lang
11674      * @param {*} value The value to check.
11675      * @returns {boolean} Returns `true` if `value` is a function, else `false`.
11676      * @example
11677      *
11678      * _.isFunction(_);
11679      * // => true
11680      *
11681      * _.isFunction(/abc/);
11682      * // => false
11683      */
11684     function isFunction(value) {
11685       if (!isObject(value)) {
11686         return false;
11687       }
11688       // The use of `Object#toString` avoids issues with the `typeof` operator
11689       // in Safari 9 which returns 'object' for typed arrays and other constructors.
11690       var tag = baseGetTag(value);
11691       return tag == funcTag || tag == genTag || tag == asyncTag || tag == proxyTag;
11692     }
11693
11694     /**
11695      * Checks if `value` is an integer.
11696      *
11697      * **Note:** This method is based on
11698      * [`Number.isInteger`](https://mdn.io/Number/isInteger).
11699      *
11700      * @static
11701      * @memberOf _
11702      * @since 4.0.0
11703      * @category Lang
11704      * @param {*} value The value to check.
11705      * @returns {boolean} Returns `true` if `value` is an integer, else `false`.
11706      * @example
11707      *
11708      * _.isInteger(3);
11709      * // => true
11710      *
11711      * _.isInteger(Number.MIN_VALUE);
11712      * // => false
11713      *
11714      * _.isInteger(Infinity);
11715      * // => false
11716      *
11717      * _.isInteger('3');
11718      * // => false
11719      */
11720     function isInteger(value) {
11721       return typeof value == 'number' && value == toInteger(value);
11722     }
11723
11724     /**
11725      * Checks if `value` is a valid array-like length.
11726      *
11727      * **Note:** This method is loosely based on
11728      * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
11729      *
11730      * @static
11731      * @memberOf _
11732      * @since 4.0.0
11733      * @category Lang
11734      * @param {*} value The value to check.
11735      * @returns {boolean} Returns `true` if `value` is a valid length, else `false`.
11736      * @example
11737      *
11738      * _.isLength(3);
11739      * // => true
11740      *
11741      * _.isLength(Number.MIN_VALUE);
11742      * // => false
11743      *
11744      * _.isLength(Infinity);
11745      * // => false
11746      *
11747      * _.isLength('3');
11748      * // => false
11749      */
11750     function isLength(value) {
11751       return typeof value == 'number' &&
11752         value > -1 && value % 1 == 0 && value <= MAX_SAFE_INTEGER;
11753     }
11754
11755     /**
11756      * Checks if `value` is the
11757      * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)
11758      * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)
11759      *
11760      * @static
11761      * @memberOf _
11762      * @since 0.1.0
11763      * @category Lang
11764      * @param {*} value The value to check.
11765      * @returns {boolean} Returns `true` if `value` is an object, else `false`.
11766      * @example
11767      *
11768      * _.isObject({});
11769      * // => true
11770      *
11771      * _.isObject([1, 2, 3]);
11772      * // => true
11773      *
11774      * _.isObject(_.noop);
11775      * // => true
11776      *
11777      * _.isObject(null);
11778      * // => false
11779      */
11780     function isObject(value) {
11781       var type = typeof value;
11782       return value != null && (type == 'object' || type == 'function');
11783     }
11784
11785     /**
11786      * Checks if `value` is object-like. A value is object-like if it's not `null`
11787      * and has a `typeof` result of "object".
11788      *
11789      * @static
11790      * @memberOf _
11791      * @since 4.0.0
11792      * @category Lang
11793      * @param {*} value The value to check.
11794      * @returns {boolean} Returns `true` if `value` is object-like, else `false`.
11795      * @example
11796      *
11797      * _.isObjectLike({});
11798      * // => true
11799      *
11800      * _.isObjectLike([1, 2, 3]);
11801      * // => true
11802      *
11803      * _.isObjectLike(_.noop);
11804      * // => false
11805      *
11806      * _.isObjectLike(null);
11807      * // => false
11808      */
11809     function isObjectLike(value) {
11810       return value != null && typeof value == 'object';
11811     }
11812
11813     /**
11814      * Checks if `value` is classified as a `Map` object.
11815      *
11816      * @static
11817      * @memberOf _
11818      * @since 4.3.0
11819      * @category Lang
11820      * @param {*} value The value to check.
11821      * @returns {boolean} Returns `true` if `value` is a map, else `false`.
11822      * @example
11823      *
11824      * _.isMap(new Map);
11825      * // => true
11826      *
11827      * _.isMap(new WeakMap);
11828      * // => false
11829      */
11830     var isMap = nodeIsMap ? baseUnary(nodeIsMap) : baseIsMap;
11831
11832     /**
11833      * Performs a partial deep comparison between `object` and `source` to
11834      * determine if `object` contains equivalent property values.
11835      *
11836      * **Note:** This method is equivalent to `_.matches` when `source` is
11837      * partially applied.
11838      *
11839      * Partial comparisons will match empty array and empty object `source`
11840      * values against any array or object value, respectively. See `_.isEqual`
11841      * for a list of supported value comparisons.
11842      *
11843      * @static
11844      * @memberOf _
11845      * @since 3.0.0
11846      * @category Lang
11847      * @param {Object} object The object to inspect.
11848      * @param {Object} source The object of property values to match.
11849      * @returns {boolean} Returns `true` if `object` is a match, else `false`.
11850      * @example
11851      *
11852      * var object = { 'a': 1, 'b': 2 };
11853      *
11854      * _.isMatch(object, { 'b': 2 });
11855      * // => true
11856      *
11857      * _.isMatch(object, { 'b': 1 });
11858      * // => false
11859      */
11860     function isMatch(object, source) {
11861       return object === source || baseIsMatch(object, source, getMatchData(source));
11862     }
11863
11864     /**
11865      * This method is like `_.isMatch` except that it accepts `customizer` which
11866      * is invoked to compare values. If `customizer` returns `undefined`, comparisons
11867      * are handled by the method instead. The `customizer` is invoked with five
11868      * arguments: (objValue, srcValue, index|key, object, source).
11869      *
11870      * @static
11871      * @memberOf _
11872      * @since 4.0.0
11873      * @category Lang
11874      * @param {Object} object The object to inspect.
11875      * @param {Object} source The object of property values to match.
11876      * @param {Function} [customizer] The function to customize comparisons.
11877      * @returns {boolean} Returns `true` if `object` is a match, else `false`.
11878      * @example
11879      *
11880      * function isGreeting(value) {
11881      *   return /^h(?:i|ello)$/.test(value);
11882      * }
11883      *
11884      * function customizer(objValue, srcValue) {
11885      *   if (isGreeting(objValue) && isGreeting(srcValue)) {
11886      *     return true;
11887      *   }
11888      * }
11889      *
11890      * var object = { 'greeting': 'hello' };
11891      * var source = { 'greeting': 'hi' };
11892      *
11893      * _.isMatchWith(object, source, customizer);
11894      * // => true
11895      */
11896     function isMatchWith(object, source, customizer) {
11897       customizer = typeof customizer == 'function' ? customizer : undefined;
11898       return baseIsMatch(object, source, getMatchData(source), customizer);
11899     }
11900
11901     /**
11902      * Checks if `value` is `NaN`.
11903      *
11904      * **Note:** This method is based on
11905      * [`Number.isNaN`](https://mdn.io/Number/isNaN) and is not the same as
11906      * global [`isNaN`](https://mdn.io/isNaN) which returns `true` for
11907      * `undefined` and other non-number values.
11908      *
11909      * @static
11910      * @memberOf _
11911      * @since 0.1.0
11912      * @category Lang
11913      * @param {*} value The value to check.
11914      * @returns {boolean} Returns `true` if `value` is `NaN`, else `false`.
11915      * @example
11916      *
11917      * _.isNaN(NaN);
11918      * // => true
11919      *
11920      * _.isNaN(new Number(NaN));
11921      * // => true
11922      *
11923      * isNaN(undefined);
11924      * // => true
11925      *
11926      * _.isNaN(undefined);
11927      * // => false
11928      */
11929     function isNaN(value) {
11930       // An `NaN` primitive is the only value that is not equal to itself.
11931       // Perform the `toStringTag` check first to avoid errors with some
11932       // ActiveX objects in IE.
11933       return isNumber(value) && value != +value;
11934     }
11935
11936     /**
11937      * Checks if `value` is a pristine native function.
11938      *
11939      * **Note:** This method can't reliably detect native functions in the presence
11940      * of the core-js package because core-js circumvents this kind of detection.
11941      * Despite multiple requests, the core-js maintainer has made it clear: any
11942      * attempt to fix the detection will be obstructed. As a result, we're left
11943      * with little choice but to throw an error. Unfortunately, this also affects
11944      * packages, like [babel-polyfill](https://www.npmjs.com/package/babel-polyfill),
11945      * which rely on core-js.
11946      *
11947      * @static
11948      * @memberOf _
11949      * @since 3.0.0
11950      * @category Lang
11951      * @param {*} value The value to check.
11952      * @returns {boolean} Returns `true` if `value` is a native function,
11953      *  else `false`.
11954      * @example
11955      *
11956      * _.isNative(Array.prototype.push);
11957      * // => true
11958      *
11959      * _.isNative(_);
11960      * // => false
11961      */
11962     function isNative(value) {
11963       if (isMaskable(value)) {
11964         throw new Error(CORE_ERROR_TEXT);
11965       }
11966       return baseIsNative(value);
11967     }
11968
11969     /**
11970      * Checks if `value` is `null`.
11971      *
11972      * @static
11973      * @memberOf _
11974      * @since 0.1.0
11975      * @category Lang
11976      * @param {*} value The value to check.
11977      * @returns {boolean} Returns `true` if `value` is `null`, else `false`.
11978      * @example
11979      *
11980      * _.isNull(null);
11981      * // => true
11982      *
11983      * _.isNull(void 0);
11984      * // => false
11985      */
11986     function isNull(value) {
11987       return value === null;
11988     }
11989
11990     /**
11991      * Checks if `value` is `null` or `undefined`.
11992      *
11993      * @static
11994      * @memberOf _
11995      * @since 4.0.0
11996      * @category Lang
11997      * @param {*} value The value to check.
11998      * @returns {boolean} Returns `true` if `value` is nullish, else `false`.
11999      * @example
12000      *
12001      * _.isNil(null);
12002      * // => true
12003      *
12004      * _.isNil(void 0);
12005      * // => true
12006      *
12007      * _.isNil(NaN);
12008      * // => false
12009      */
12010     function isNil(value) {
12011       return value == null;
12012     }
12013
12014     /**
12015      * Checks if `value` is classified as a `Number` primitive or object.
12016      *
12017      * **Note:** To exclude `Infinity`, `-Infinity`, and `NaN`, which are
12018      * classified as numbers, use the `_.isFinite` method.
12019      *
12020      * @static
12021      * @memberOf _
12022      * @since 0.1.0
12023      * @category Lang
12024      * @param {*} value The value to check.
12025      * @returns {boolean} Returns `true` if `value` is a number, else `false`.
12026      * @example
12027      *
12028      * _.isNumber(3);
12029      * // => true
12030      *
12031      * _.isNumber(Number.MIN_VALUE);
12032      * // => true
12033      *
12034      * _.isNumber(Infinity);
12035      * // => true
12036      *
12037      * _.isNumber('3');
12038      * // => false
12039      */
12040     function isNumber(value) {
12041       return typeof value == 'number' ||
12042         (isObjectLike(value) && baseGetTag(value) == numberTag);
12043     }
12044
12045     /**
12046      * Checks if `value` is a plain object, that is, an object created by the
12047      * `Object` constructor or one with a `[[Prototype]]` of `null`.
12048      *
12049      * @static
12050      * @memberOf _
12051      * @since 0.8.0
12052      * @category Lang
12053      * @param {*} value The value to check.
12054      * @returns {boolean} Returns `true` if `value` is a plain object, else `false`.
12055      * @example
12056      *
12057      * function Foo() {
12058      *   this.a = 1;
12059      * }
12060      *
12061      * _.isPlainObject(new Foo);
12062      * // => false
12063      *
12064      * _.isPlainObject([1, 2, 3]);
12065      * // => false
12066      *
12067      * _.isPlainObject({ 'x': 0, 'y': 0 });
12068      * // => true
12069      *
12070      * _.isPlainObject(Object.create(null));
12071      * // => true
12072      */
12073     function isPlainObject(value) {
12074       if (!isObjectLike(value) || baseGetTag(value) != objectTag) {
12075         return false;
12076       }
12077       var proto = getPrototype(value);
12078       if (proto === null) {
12079         return true;
12080       }
12081       var Ctor = hasOwnProperty.call(proto, 'constructor') && proto.constructor;
12082       return typeof Ctor == 'function' && Ctor instanceof Ctor &&
12083         funcToString.call(Ctor) == objectCtorString;
12084     }
12085
12086     /**
12087      * Checks if `value` is classified as a `RegExp` object.
12088      *
12089      * @static
12090      * @memberOf _
12091      * @since 0.1.0
12092      * @category Lang
12093      * @param {*} value The value to check.
12094      * @returns {boolean} Returns `true` if `value` is a regexp, else `false`.
12095      * @example
12096      *
12097      * _.isRegExp(/abc/);
12098      * // => true
12099      *
12100      * _.isRegExp('/abc/');
12101      * // => false
12102      */
12103     var isRegExp = nodeIsRegExp ? baseUnary(nodeIsRegExp) : baseIsRegExp;
12104
12105     /**
12106      * Checks if `value` is a safe integer. An integer is safe if it's an IEEE-754
12107      * double precision number which isn't the result of a rounded unsafe integer.
12108      *
12109      * **Note:** This method is based on
12110      * [`Number.isSafeInteger`](https://mdn.io/Number/isSafeInteger).
12111      *
12112      * @static
12113      * @memberOf _
12114      * @since 4.0.0
12115      * @category Lang
12116      * @param {*} value The value to check.
12117      * @returns {boolean} Returns `true` if `value` is a safe integer, else `false`.
12118      * @example
12119      *
12120      * _.isSafeInteger(3);
12121      * // => true
12122      *
12123      * _.isSafeInteger(Number.MIN_VALUE);
12124      * // => false
12125      *
12126      * _.isSafeInteger(Infinity);
12127      * // => false
12128      *
12129      * _.isSafeInteger('3');
12130      * // => false
12131      */
12132     function isSafeInteger(value) {
12133       return isInteger(value) && value >= -MAX_SAFE_INTEGER && value <= MAX_SAFE_INTEGER;
12134     }
12135
12136     /**
12137      * Checks if `value` is classified as a `Set` object.
12138      *
12139      * @static
12140      * @memberOf _
12141      * @since 4.3.0
12142      * @category Lang
12143      * @param {*} value The value to check.
12144      * @returns {boolean} Returns `true` if `value` is a set, else `false`.
12145      * @example
12146      *
12147      * _.isSet(new Set);
12148      * // => true
12149      *
12150      * _.isSet(new WeakSet);
12151      * // => false
12152      */
12153     var isSet = nodeIsSet ? baseUnary(nodeIsSet) : baseIsSet;
12154
12155     /**
12156      * Checks if `value` is classified as a `String` primitive or object.
12157      *
12158      * @static
12159      * @since 0.1.0
12160      * @memberOf _
12161      * @category Lang
12162      * @param {*} value The value to check.
12163      * @returns {boolean} Returns `true` if `value` is a string, else `false`.
12164      * @example
12165      *
12166      * _.isString('abc');
12167      * // => true
12168      *
12169      * _.isString(1);
12170      * // => false
12171      */
12172     function isString(value) {
12173       return typeof value == 'string' ||
12174         (!isArray(value) && isObjectLike(value) && baseGetTag(value) == stringTag);
12175     }
12176
12177     /**
12178      * Checks if `value` is classified as a `Symbol` primitive or object.
12179      *
12180      * @static
12181      * @memberOf _
12182      * @since 4.0.0
12183      * @category Lang
12184      * @param {*} value The value to check.
12185      * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.
12186      * @example
12187      *
12188      * _.isSymbol(Symbol.iterator);
12189      * // => true
12190      *
12191      * _.isSymbol('abc');
12192      * // => false
12193      */
12194     function isSymbol(value) {
12195       return typeof value == 'symbol' ||
12196         (isObjectLike(value) && baseGetTag(value) == symbolTag);
12197     }
12198
12199     /**
12200      * Checks if `value` is classified as a typed array.
12201      *
12202      * @static
12203      * @memberOf _
12204      * @since 3.0.0
12205      * @category Lang
12206      * @param {*} value The value to check.
12207      * @returns {boolean} Returns `true` if `value` is a typed array, else `false`.
12208      * @example
12209      *
12210      * _.isTypedArray(new Uint8Array);
12211      * // => true
12212      *
12213      * _.isTypedArray([]);
12214      * // => false
12215      */
12216     var isTypedArray = nodeIsTypedArray ? baseUnary(nodeIsTypedArray) : baseIsTypedArray;
12217
12218     /**
12219      * Checks if `value` is `undefined`.
12220      *
12221      * @static
12222      * @since 0.1.0
12223      * @memberOf _
12224      * @category Lang
12225      * @param {*} value The value to check.
12226      * @returns {boolean} Returns `true` if `value` is `undefined`, else `false`.
12227      * @example
12228      *
12229      * _.isUndefined(void 0);
12230      * // => true
12231      *
12232      * _.isUndefined(null);
12233      * // => false
12234      */
12235     function isUndefined(value) {
12236       return value === undefined;
12237     }
12238
12239     /**
12240      * Checks if `value` is classified as a `WeakMap` object.
12241      *
12242      * @static
12243      * @memberOf _
12244      * @since 4.3.0
12245      * @category Lang
12246      * @param {*} value The value to check.
12247      * @returns {boolean} Returns `true` if `value` is a weak map, else `false`.
12248      * @example
12249      *
12250      * _.isWeakMap(new WeakMap);
12251      * // => true
12252      *
12253      * _.isWeakMap(new Map);
12254      * // => false
12255      */
12256     function isWeakMap(value) {
12257       return isObjectLike(value) && getTag(value) == weakMapTag;
12258     }
12259
12260     /**
12261      * Checks if `value` is classified as a `WeakSet` object.
12262      *
12263      * @static
12264      * @memberOf _
12265      * @since 4.3.0
12266      * @category Lang
12267      * @param {*} value The value to check.
12268      * @returns {boolean} Returns `true` if `value` is a weak set, else `false`.
12269      * @example
12270      *
12271      * _.isWeakSet(new WeakSet);
12272      * // => true
12273      *
12274      * _.isWeakSet(new Set);
12275      * // => false
12276      */
12277     function isWeakSet(value) {
12278       return isObjectLike(value) && baseGetTag(value) == weakSetTag;
12279     }
12280
12281     /**
12282      * Checks if `value` is less than `other`.
12283      *
12284      * @static
12285      * @memberOf _
12286      * @since 3.9.0
12287      * @category Lang
12288      * @param {*} value The value to compare.
12289      * @param {*} other The other value to compare.
12290      * @returns {boolean} Returns `true` if `value` is less than `other`,
12291      *  else `false`.
12292      * @see _.gt
12293      * @example
12294      *
12295      * _.lt(1, 3);
12296      * // => true
12297      *
12298      * _.lt(3, 3);
12299      * // => false
12300      *
12301      * _.lt(3, 1);
12302      * // => false
12303      */
12304     var lt = createRelationalOperation(baseLt);
12305
12306     /**
12307      * Checks if `value` is less than or equal to `other`.
12308      *
12309      * @static
12310      * @memberOf _
12311      * @since 3.9.0
12312      * @category Lang
12313      * @param {*} value The value to compare.
12314      * @param {*} other The other value to compare.
12315      * @returns {boolean} Returns `true` if `value` is less than or equal to
12316      *  `other`, else `false`.
12317      * @see _.gte
12318      * @example
12319      *
12320      * _.lte(1, 3);
12321      * // => true
12322      *
12323      * _.lte(3, 3);
12324      * // => true
12325      *
12326      * _.lte(3, 1);
12327      * // => false
12328      */
12329     var lte = createRelationalOperation(function(value, other) {
12330       return value <= other;
12331     });
12332
12333     /**
12334      * Converts `value` to an array.
12335      *
12336      * @static
12337      * @since 0.1.0
12338      * @memberOf _
12339      * @category Lang
12340      * @param {*} value The value to convert.
12341      * @returns {Array} Returns the converted array.
12342      * @example
12343      *
12344      * _.toArray({ 'a': 1, 'b': 2 });
12345      * // => [1, 2]
12346      *
12347      * _.toArray('abc');
12348      * // => ['a', 'b', 'c']
12349      *
12350      * _.toArray(1);
12351      * // => []
12352      *
12353      * _.toArray(null);
12354      * // => []
12355      */
12356     function toArray(value) {
12357       if (!value) {
12358         return [];
12359       }
12360       if (isArrayLike(value)) {
12361         return isString(value) ? stringToArray(value) : copyArray(value);
12362       }
12363       if (symIterator && value[symIterator]) {
12364         return iteratorToArray(value[symIterator]());
12365       }
12366       var tag = getTag(value),
12367           func = tag == mapTag ? mapToArray : (tag == setTag ? setToArray : values);
12368
12369       return func(value);
12370     }
12371
12372     /**
12373      * Converts `value` to a finite number.
12374      *
12375      * @static
12376      * @memberOf _
12377      * @since 4.12.0
12378      * @category Lang
12379      * @param {*} value The value to convert.
12380      * @returns {number} Returns the converted number.
12381      * @example
12382      *
12383      * _.toFinite(3.2);
12384      * // => 3.2
12385      *
12386      * _.toFinite(Number.MIN_VALUE);
12387      * // => 5e-324
12388      *
12389      * _.toFinite(Infinity);
12390      * // => 1.7976931348623157e+308
12391      *
12392      * _.toFinite('3.2');
12393      * // => 3.2
12394      */
12395     function toFinite(value) {
12396       if (!value) {
12397         return value === 0 ? value : 0;
12398       }
12399       value = toNumber(value);
12400       if (value === INFINITY || value === -INFINITY) {
12401         var sign = (value < 0 ? -1 : 1);
12402         return sign * MAX_INTEGER;
12403       }
12404       return value === value ? value : 0;
12405     }
12406
12407     /**
12408      * Converts `value` to an integer.
12409      *
12410      * **Note:** This method is loosely based on
12411      * [`ToInteger`](http://www.ecma-international.org/ecma-262/7.0/#sec-tointeger).
12412      *
12413      * @static
12414      * @memberOf _
12415      * @since 4.0.0
12416      * @category Lang
12417      * @param {*} value The value to convert.
12418      * @returns {number} Returns the converted integer.
12419      * @example
12420      *
12421      * _.toInteger(3.2);
12422      * // => 3
12423      *
12424      * _.toInteger(Number.MIN_VALUE);
12425      * // => 0
12426      *
12427      * _.toInteger(Infinity);
12428      * // => 1.7976931348623157e+308
12429      *
12430      * _.toInteger('3.2');
12431      * // => 3
12432      */
12433     function toInteger(value) {
12434       var result = toFinite(value),
12435           remainder = result % 1;
12436
12437       return result === result ? (remainder ? result - remainder : result) : 0;
12438     }
12439
12440     /**
12441      * Converts `value` to an integer suitable for use as the length of an
12442      * array-like object.
12443      *
12444      * **Note:** This method is based on
12445      * [`ToLength`](http://ecma-international.org/ecma-262/7.0/#sec-tolength).
12446      *
12447      * @static
12448      * @memberOf _
12449      * @since 4.0.0
12450      * @category Lang
12451      * @param {*} value The value to convert.
12452      * @returns {number} Returns the converted integer.
12453      * @example
12454      *
12455      * _.toLength(3.2);
12456      * // => 3
12457      *
12458      * _.toLength(Number.MIN_VALUE);
12459      * // => 0
12460      *
12461      * _.toLength(Infinity);
12462      * // => 4294967295
12463      *
12464      * _.toLength('3.2');
12465      * // => 3
12466      */
12467     function toLength(value) {
12468       return value ? baseClamp(toInteger(value), 0, MAX_ARRAY_LENGTH) : 0;
12469     }
12470
12471     /**
12472      * Converts `value` to a number.
12473      *
12474      * @static
12475      * @memberOf _
12476      * @since 4.0.0
12477      * @category Lang
12478      * @param {*} value The value to process.
12479      * @returns {number} Returns the number.
12480      * @example
12481      *
12482      * _.toNumber(3.2);
12483      * // => 3.2
12484      *
12485      * _.toNumber(Number.MIN_VALUE);
12486      * // => 5e-324
12487      *
12488      * _.toNumber(Infinity);
12489      * // => Infinity
12490      *
12491      * _.toNumber('3.2');
12492      * // => 3.2
12493      */
12494     function toNumber(value) {
12495       if (typeof value == 'number') {
12496         return value;
12497       }
12498       if (isSymbol(value)) {
12499         return NAN;
12500       }
12501       if (isObject(value)) {
12502         var other = typeof value.valueOf == 'function' ? value.valueOf() : value;
12503         value = isObject(other) ? (other + '') : other;
12504       }
12505       if (typeof value != 'string') {
12506         return value === 0 ? value : +value;
12507       }
12508       value = value.replace(reTrim, '');
12509       var isBinary = reIsBinary.test(value);
12510       return (isBinary || reIsOctal.test(value))
12511         ? freeParseInt(value.slice(2), isBinary ? 2 : 8)
12512         : (reIsBadHex.test(value) ? NAN : +value);
12513     }
12514
12515     /**
12516      * Converts `value` to a plain object flattening inherited enumerable string
12517      * keyed properties of `value` to own properties of the plain object.
12518      *
12519      * @static
12520      * @memberOf _
12521      * @since 3.0.0
12522      * @category Lang
12523      * @param {*} value The value to convert.
12524      * @returns {Object} Returns the converted plain object.
12525      * @example
12526      *
12527      * function Foo() {
12528      *   this.b = 2;
12529      * }
12530      *
12531      * Foo.prototype.c = 3;
12532      *
12533      * _.assign({ 'a': 1 }, new Foo);
12534      * // => { 'a': 1, 'b': 2 }
12535      *
12536      * _.assign({ 'a': 1 }, _.toPlainObject(new Foo));
12537      * // => { 'a': 1, 'b': 2, 'c': 3 }
12538      */
12539     function toPlainObject(value) {
12540       return copyObject(value, keysIn(value));
12541     }
12542
12543     /**
12544      * Converts `value` to a safe integer. A safe integer can be compared and
12545      * represented correctly.
12546      *
12547      * @static
12548      * @memberOf _
12549      * @since 4.0.0
12550      * @category Lang
12551      * @param {*} value The value to convert.
12552      * @returns {number} Returns the converted integer.
12553      * @example
12554      *
12555      * _.toSafeInteger(3.2);
12556      * // => 3
12557      *
12558      * _.toSafeInteger(Number.MIN_VALUE);
12559      * // => 0
12560      *
12561      * _.toSafeInteger(Infinity);
12562      * // => 9007199254740991
12563      *
12564      * _.toSafeInteger('3.2');
12565      * // => 3
12566      */
12567     function toSafeInteger(value) {
12568       return baseClamp(toInteger(value), -MAX_SAFE_INTEGER, MAX_SAFE_INTEGER);
12569     }
12570
12571     /**
12572      * Converts `value` to a string. An empty string is returned for `null`
12573      * and `undefined` values. The sign of `-0` is preserved.
12574      *
12575      * @static
12576      * @memberOf _
12577      * @since 4.0.0
12578      * @category Lang
12579      * @param {*} value The value to convert.
12580      * @returns {string} Returns the converted string.
12581      * @example
12582      *
12583      * _.toString(null);
12584      * // => ''
12585      *
12586      * _.toString(-0);
12587      * // => '-0'
12588      *
12589      * _.toString([1, 2, 3]);
12590      * // => '1,2,3'
12591      */
12592     function toString(value) {
12593       return value == null ? '' : baseToString(value);
12594     }
12595
12596     /*------------------------------------------------------------------------*/
12597
12598     /**
12599      * Assigns own enumerable string keyed properties of source objects to the
12600      * destination object. Source objects are applied from left to right.
12601      * Subsequent sources overwrite property assignments of previous sources.
12602      *
12603      * **Note:** This method mutates `object` and is loosely based on
12604      * [`Object.assign`](https://mdn.io/Object/assign).
12605      *
12606      * @static
12607      * @memberOf _
12608      * @since 0.10.0
12609      * @category Object
12610      * @param {Object} object The destination object.
12611      * @param {...Object} [sources] The source objects.
12612      * @returns {Object} Returns `object`.
12613      * @see _.assignIn
12614      * @example
12615      *
12616      * function Foo() {
12617      *   this.a = 1;
12618      * }
12619      *
12620      * function Bar() {
12621      *   this.c = 3;
12622      * }
12623      *
12624      * Foo.prototype.b = 2;
12625      * Bar.prototype.d = 4;
12626      *
12627      * _.assign({ 'a': 0 }, new Foo, new Bar);
12628      * // => { 'a': 1, 'c': 3 }
12629      */
12630     var assign = createAssigner(function(object, source) {
12631       if (isPrototype(source) || isArrayLike(source)) {
12632         copyObject(source, keys(source), object);
12633         return;
12634       }
12635       for (var key in source) {
12636         if (hasOwnProperty.call(source, key)) {
12637           assignValue(object, key, source[key]);
12638         }
12639       }
12640     });
12641
12642     /**
12643      * This method is like `_.assign` except that it iterates over own and
12644      * inherited source properties.
12645      *
12646      * **Note:** This method mutates `object`.
12647      *
12648      * @static
12649      * @memberOf _
12650      * @since 4.0.0
12651      * @alias extend
12652      * @category Object
12653      * @param {Object} object The destination object.
12654      * @param {...Object} [sources] The source objects.
12655      * @returns {Object} Returns `object`.
12656      * @see _.assign
12657      * @example
12658      *
12659      * function Foo() {
12660      *   this.a = 1;
12661      * }
12662      *
12663      * function Bar() {
12664      *   this.c = 3;
12665      * }
12666      *
12667      * Foo.prototype.b = 2;
12668      * Bar.prototype.d = 4;
12669      *
12670      * _.assignIn({ 'a': 0 }, new Foo, new Bar);
12671      * // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }
12672      */
12673     var assignIn = createAssigner(function(object, source) {
12674       copyObject(source, keysIn(source), object);
12675     });
12676
12677     /**
12678      * This method is like `_.assignIn` except that it accepts `customizer`
12679      * which is invoked to produce the assigned values. If `customizer` returns
12680      * `undefined`, assignment is handled by the method instead. The `customizer`
12681      * is invoked with five arguments: (objValue, srcValue, key, object, source).
12682      *
12683      * **Note:** This method mutates `object`.
12684      *
12685      * @static
12686      * @memberOf _
12687      * @since 4.0.0
12688      * @alias extendWith
12689      * @category Object
12690      * @param {Object} object The destination object.
12691      * @param {...Object} sources The source objects.
12692      * @param {Function} [customizer] The function to customize assigned values.
12693      * @returns {Object} Returns `object`.
12694      * @see _.assignWith
12695      * @example
12696      *
12697      * function customizer(objValue, srcValue) {
12698      *   return _.isUndefined(objValue) ? srcValue : objValue;
12699      * }
12700      *
12701      * var defaults = _.partialRight(_.assignInWith, customizer);
12702      *
12703      * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
12704      * // => { 'a': 1, 'b': 2 }
12705      */
12706     var assignInWith = createAssigner(function(object, source, srcIndex, customizer) {
12707       copyObject(source, keysIn(source), object, customizer);
12708     });
12709
12710     /**
12711      * This method is like `_.assign` except that it accepts `customizer`
12712      * which is invoked to produce the assigned values. If `customizer` returns
12713      * `undefined`, assignment is handled by the method instead. The `customizer`
12714      * is invoked with five arguments: (objValue, srcValue, key, object, source).
12715      *
12716      * **Note:** This method mutates `object`.
12717      *
12718      * @static
12719      * @memberOf _
12720      * @since 4.0.0
12721      * @category Object
12722      * @param {Object} object The destination object.
12723      * @param {...Object} sources The source objects.
12724      * @param {Function} [customizer] The function to customize assigned values.
12725      * @returns {Object} Returns `object`.
12726      * @see _.assignInWith
12727      * @example
12728      *
12729      * function customizer(objValue, srcValue) {
12730      *   return _.isUndefined(objValue) ? srcValue : objValue;
12731      * }
12732      *
12733      * var defaults = _.partialRight(_.assignWith, customizer);
12734      *
12735      * defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
12736      * // => { 'a': 1, 'b': 2 }
12737      */
12738     var assignWith = createAssigner(function(object, source, srcIndex, customizer) {
12739       copyObject(source, keys(source), object, customizer);
12740     });
12741
12742     /**
12743      * Creates an array of values corresponding to `paths` of `object`.
12744      *
12745      * @static
12746      * @memberOf _
12747      * @since 1.0.0
12748      * @category Object
12749      * @param {Object} object The object to iterate over.
12750      * @param {...(string|string[])} [paths] The property paths to pick.
12751      * @returns {Array} Returns the picked values.
12752      * @example
12753      *
12754      * var object = { 'a': [{ 'b': { 'c': 3 } }, 4] };
12755      *
12756      * _.at(object, ['a[0].b.c', 'a[1]']);
12757      * // => [3, 4]
12758      */
12759     var at = flatRest(baseAt);
12760
12761     /**
12762      * Creates an object that inherits from the `prototype` object. If a
12763      * `properties` object is given, its own enumerable string keyed properties
12764      * are assigned to the created object.
12765      *
12766      * @static
12767      * @memberOf _
12768      * @since 2.3.0
12769      * @category Object
12770      * @param {Object} prototype The object to inherit from.
12771      * @param {Object} [properties] The properties to assign to the object.
12772      * @returns {Object} Returns the new object.
12773      * @example
12774      *
12775      * function Shape() {
12776      *   this.x = 0;
12777      *   this.y = 0;
12778      * }
12779      *
12780      * function Circle() {
12781      *   Shape.call(this);
12782      * }
12783      *
12784      * Circle.prototype = _.create(Shape.prototype, {
12785      *   'constructor': Circle
12786      * });
12787      *
12788      * var circle = new Circle;
12789      * circle instanceof Circle;
12790      * // => true
12791      *
12792      * circle instanceof Shape;
12793      * // => true
12794      */
12795     function create(prototype, properties) {
12796       var result = baseCreate(prototype);
12797       return properties == null ? result : baseAssign(result, properties);
12798     }
12799
12800     /**
12801      * Assigns own and inherited enumerable string keyed properties of source
12802      * objects to the destination object for all destination properties that
12803      * resolve to `undefined`. Source objects are applied from left to right.
12804      * Once a property is set, additional values of the same property are ignored.
12805      *
12806      * **Note:** This method mutates `object`.
12807      *
12808      * @static
12809      * @since 0.1.0
12810      * @memberOf _
12811      * @category Object
12812      * @param {Object} object The destination object.
12813      * @param {...Object} [sources] The source objects.
12814      * @returns {Object} Returns `object`.
12815      * @see _.defaultsDeep
12816      * @example
12817      *
12818      * _.defaults({ 'a': 1 }, { 'b': 2 }, { 'a': 3 });
12819      * // => { 'a': 1, 'b': 2 }
12820      */
12821     var defaults = baseRest(function(args) {
12822       args.push(undefined, assignInDefaults);
12823       return apply(assignInWith, undefined, args);
12824     });
12825
12826     /**
12827      * This method is like `_.defaults` except that it recursively assigns
12828      * default properties.
12829      *
12830      * **Note:** This method mutates `object`.
12831      *
12832      * @static
12833      * @memberOf _
12834      * @since 3.10.0
12835      * @category Object
12836      * @param {Object} object The destination object.
12837      * @param {...Object} [sources] The source objects.
12838      * @returns {Object} Returns `object`.
12839      * @see _.defaults
12840      * @example
12841      *
12842      * _.defaultsDeep({ 'a': { 'b': 2 } }, { 'a': { 'b': 1, 'c': 3 } });
12843      * // => { 'a': { 'b': 2, 'c': 3 } }
12844      */
12845     var defaultsDeep = baseRest(function(args) {
12846       args.push(undefined, mergeDefaults);
12847       return apply(mergeWith, undefined, args);
12848     });
12849
12850     /**
12851      * This method is like `_.find` except that it returns the key of the first
12852      * element `predicate` returns truthy for instead of the element itself.
12853      *
12854      * @static
12855      * @memberOf _
12856      * @since 1.1.0
12857      * @category Object
12858      * @param {Object} object The object to inspect.
12859      * @param {Function} [predicate=_.identity] The function invoked per iteration.
12860      * @returns {string|undefined} Returns the key of the matched element,
12861      *  else `undefined`.
12862      * @example
12863      *
12864      * var users = {
12865      *   'barney':  { 'age': 36, 'active': true },
12866      *   'fred':    { 'age': 40, 'active': false },
12867      *   'pebbles': { 'age': 1,  'active': true }
12868      * };
12869      *
12870      * _.findKey(users, function(o) { return o.age < 40; });
12871      * // => 'barney' (iteration order is not guaranteed)
12872      *
12873      * // The `_.matches` iteratee shorthand.
12874      * _.findKey(users, { 'age': 1, 'active': true });
12875      * // => 'pebbles'
12876      *
12877      * // The `_.matchesProperty` iteratee shorthand.
12878      * _.findKey(users, ['active', false]);
12879      * // => 'fred'
12880      *
12881      * // The `_.property` iteratee shorthand.
12882      * _.findKey(users, 'active');
12883      * // => 'barney'
12884      */
12885     function findKey(object, predicate) {
12886       return baseFindKey(object, getIteratee(predicate, 3), baseForOwn);
12887     }
12888
12889     /**
12890      * This method is like `_.findKey` except that it iterates over elements of
12891      * a collection in the opposite order.
12892      *
12893      * @static
12894      * @memberOf _
12895      * @since 2.0.0
12896      * @category Object
12897      * @param {Object} object The object to inspect.
12898      * @param {Function} [predicate=_.identity] The function invoked per iteration.
12899      * @returns {string|undefined} Returns the key of the matched element,
12900      *  else `undefined`.
12901      * @example
12902      *
12903      * var users = {
12904      *   'barney':  { 'age': 36, 'active': true },
12905      *   'fred':    { 'age': 40, 'active': false },
12906      *   'pebbles': { 'age': 1,  'active': true }
12907      * };
12908      *
12909      * _.findLastKey(users, function(o) { return o.age < 40; });
12910      * // => returns 'pebbles' assuming `_.findKey` returns 'barney'
12911      *
12912      * // The `_.matches` iteratee shorthand.
12913      * _.findLastKey(users, { 'age': 36, 'active': true });
12914      * // => 'barney'
12915      *
12916      * // The `_.matchesProperty` iteratee shorthand.
12917      * _.findLastKey(users, ['active', false]);
12918      * // => 'fred'
12919      *
12920      * // The `_.property` iteratee shorthand.
12921      * _.findLastKey(users, 'active');
12922      * // => 'pebbles'
12923      */
12924     function findLastKey(object, predicate) {
12925       return baseFindKey(object, getIteratee(predicate, 3), baseForOwnRight);
12926     }
12927
12928     /**
12929      * Iterates over own and inherited enumerable string keyed properties of an
12930      * object and invokes `iteratee` for each property. The iteratee is invoked
12931      * with three arguments: (value, key, object). Iteratee functions may exit
12932      * iteration early by explicitly returning `false`.
12933      *
12934      * @static
12935      * @memberOf _
12936      * @since 0.3.0
12937      * @category Object
12938      * @param {Object} object The object to iterate over.
12939      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
12940      * @returns {Object} Returns `object`.
12941      * @see _.forInRight
12942      * @example
12943      *
12944      * function Foo() {
12945      *   this.a = 1;
12946      *   this.b = 2;
12947      * }
12948      *
12949      * Foo.prototype.c = 3;
12950      *
12951      * _.forIn(new Foo, function(value, key) {
12952      *   console.log(key);
12953      * });
12954      * // => Logs 'a', 'b', then 'c' (iteration order is not guaranteed).
12955      */
12956     function forIn(object, iteratee) {
12957       return object == null
12958         ? object
12959         : baseFor(object, getIteratee(iteratee, 3), keysIn);
12960     }
12961
12962     /**
12963      * This method is like `_.forIn` except that it iterates over properties of
12964      * `object` in the opposite order.
12965      *
12966      * @static
12967      * @memberOf _
12968      * @since 2.0.0
12969      * @category Object
12970      * @param {Object} object The object to iterate over.
12971      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
12972      * @returns {Object} Returns `object`.
12973      * @see _.forIn
12974      * @example
12975      *
12976      * function Foo() {
12977      *   this.a = 1;
12978      *   this.b = 2;
12979      * }
12980      *
12981      * Foo.prototype.c = 3;
12982      *
12983      * _.forInRight(new Foo, function(value, key) {
12984      *   console.log(key);
12985      * });
12986      * // => Logs 'c', 'b', then 'a' assuming `_.forIn` logs 'a', 'b', then 'c'.
12987      */
12988     function forInRight(object, iteratee) {
12989       return object == null
12990         ? object
12991         : baseForRight(object, getIteratee(iteratee, 3), keysIn);
12992     }
12993
12994     /**
12995      * Iterates over own enumerable string keyed properties of an object and
12996      * invokes `iteratee` for each property. The iteratee is invoked with three
12997      * arguments: (value, key, object). Iteratee functions may exit iteration
12998      * early by explicitly returning `false`.
12999      *
13000      * @static
13001      * @memberOf _
13002      * @since 0.3.0
13003      * @category Object
13004      * @param {Object} object The object to iterate over.
13005      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13006      * @returns {Object} Returns `object`.
13007      * @see _.forOwnRight
13008      * @example
13009      *
13010      * function Foo() {
13011      *   this.a = 1;
13012      *   this.b = 2;
13013      * }
13014      *
13015      * Foo.prototype.c = 3;
13016      *
13017      * _.forOwn(new Foo, function(value, key) {
13018      *   console.log(key);
13019      * });
13020      * // => Logs 'a' then 'b' (iteration order is not guaranteed).
13021      */
13022     function forOwn(object, iteratee) {
13023       return object && baseForOwn(object, getIteratee(iteratee, 3));
13024     }
13025
13026     /**
13027      * This method is like `_.forOwn` except that it iterates over properties of
13028      * `object` in the opposite order.
13029      *
13030      * @static
13031      * @memberOf _
13032      * @since 2.0.0
13033      * @category Object
13034      * @param {Object} object The object to iterate over.
13035      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13036      * @returns {Object} Returns `object`.
13037      * @see _.forOwn
13038      * @example
13039      *
13040      * function Foo() {
13041      *   this.a = 1;
13042      *   this.b = 2;
13043      * }
13044      *
13045      * Foo.prototype.c = 3;
13046      *
13047      * _.forOwnRight(new Foo, function(value, key) {
13048      *   console.log(key);
13049      * });
13050      * // => Logs 'b' then 'a' assuming `_.forOwn` logs 'a' then 'b'.
13051      */
13052     function forOwnRight(object, iteratee) {
13053       return object && baseForOwnRight(object, getIteratee(iteratee, 3));
13054     }
13055
13056     /**
13057      * Creates an array of function property names from own enumerable properties
13058      * of `object`.
13059      *
13060      * @static
13061      * @since 0.1.0
13062      * @memberOf _
13063      * @category Object
13064      * @param {Object} object The object to inspect.
13065      * @returns {Array} Returns the function names.
13066      * @see _.functionsIn
13067      * @example
13068      *
13069      * function Foo() {
13070      *   this.a = _.constant('a');
13071      *   this.b = _.constant('b');
13072      * }
13073      *
13074      * Foo.prototype.c = _.constant('c');
13075      *
13076      * _.functions(new Foo);
13077      * // => ['a', 'b']
13078      */
13079     function functions(object) {
13080       return object == null ? [] : baseFunctions(object, keys(object));
13081     }
13082
13083     /**
13084      * Creates an array of function property names from own and inherited
13085      * enumerable properties of `object`.
13086      *
13087      * @static
13088      * @memberOf _
13089      * @since 4.0.0
13090      * @category Object
13091      * @param {Object} object The object to inspect.
13092      * @returns {Array} Returns the function names.
13093      * @see _.functions
13094      * @example
13095      *
13096      * function Foo() {
13097      *   this.a = _.constant('a');
13098      *   this.b = _.constant('b');
13099      * }
13100      *
13101      * Foo.prototype.c = _.constant('c');
13102      *
13103      * _.functionsIn(new Foo);
13104      * // => ['a', 'b', 'c']
13105      */
13106     function functionsIn(object) {
13107       return object == null ? [] : baseFunctions(object, keysIn(object));
13108     }
13109
13110     /**
13111      * Gets the value at `path` of `object`. If the resolved value is
13112      * `undefined`, the `defaultValue` is returned in its place.
13113      *
13114      * @static
13115      * @memberOf _
13116      * @since 3.7.0
13117      * @category Object
13118      * @param {Object} object The object to query.
13119      * @param {Array|string} path The path of the property to get.
13120      * @param {*} [defaultValue] The value returned for `undefined` resolved values.
13121      * @returns {*} Returns the resolved value.
13122      * @example
13123      *
13124      * var object = { 'a': [{ 'b': { 'c': 3 } }] };
13125      *
13126      * _.get(object, 'a[0].b.c');
13127      * // => 3
13128      *
13129      * _.get(object, ['a', '0', 'b', 'c']);
13130      * // => 3
13131      *
13132      * _.get(object, 'a.b.c', 'default');
13133      * // => 'default'
13134      */
13135     function get(object, path, defaultValue) {
13136       var result = object == null ? undefined : baseGet(object, path);
13137       return result === undefined ? defaultValue : result;
13138     }
13139
13140     /**
13141      * Checks if `path` is a direct property of `object`.
13142      *
13143      * @static
13144      * @since 0.1.0
13145      * @memberOf _
13146      * @category Object
13147      * @param {Object} object The object to query.
13148      * @param {Array|string} path The path to check.
13149      * @returns {boolean} Returns `true` if `path` exists, else `false`.
13150      * @example
13151      *
13152      * var object = { 'a': { 'b': 2 } };
13153      * var other = _.create({ 'a': _.create({ 'b': 2 }) });
13154      *
13155      * _.has(object, 'a');
13156      * // => true
13157      *
13158      * _.has(object, 'a.b');
13159      * // => true
13160      *
13161      * _.has(object, ['a', 'b']);
13162      * // => true
13163      *
13164      * _.has(other, 'a');
13165      * // => false
13166      */
13167     function has(object, path) {
13168       return object != null && hasPath(object, path, baseHas);
13169     }
13170
13171     /**
13172      * Checks if `path` is a direct or inherited property of `object`.
13173      *
13174      * @static
13175      * @memberOf _
13176      * @since 4.0.0
13177      * @category Object
13178      * @param {Object} object The object to query.
13179      * @param {Array|string} path The path to check.
13180      * @returns {boolean} Returns `true` if `path` exists, else `false`.
13181      * @example
13182      *
13183      * var object = _.create({ 'a': _.create({ 'b': 2 }) });
13184      *
13185      * _.hasIn(object, 'a');
13186      * // => true
13187      *
13188      * _.hasIn(object, 'a.b');
13189      * // => true
13190      *
13191      * _.hasIn(object, ['a', 'b']);
13192      * // => true
13193      *
13194      * _.hasIn(object, 'b');
13195      * // => false
13196      */
13197     function hasIn(object, path) {
13198       return object != null && hasPath(object, path, baseHasIn);
13199     }
13200
13201     /**
13202      * Creates an object composed of the inverted keys and values of `object`.
13203      * If `object` contains duplicate values, subsequent values overwrite
13204      * property assignments of previous values.
13205      *
13206      * @static
13207      * @memberOf _
13208      * @since 0.7.0
13209      * @category Object
13210      * @param {Object} object The object to invert.
13211      * @returns {Object} Returns the new inverted object.
13212      * @example
13213      *
13214      * var object = { 'a': 1, 'b': 2, 'c': 1 };
13215      *
13216      * _.invert(object);
13217      * // => { '1': 'c', '2': 'b' }
13218      */
13219     var invert = createInverter(function(result, value, key) {
13220       result[value] = key;
13221     }, constant(identity));
13222
13223     /**
13224      * This method is like `_.invert` except that the inverted object is generated
13225      * from the results of running each element of `object` thru `iteratee`. The
13226      * corresponding inverted value of each inverted key is an array of keys
13227      * responsible for generating the inverted value. The iteratee is invoked
13228      * with one argument: (value).
13229      *
13230      * @static
13231      * @memberOf _
13232      * @since 4.1.0
13233      * @category Object
13234      * @param {Object} object The object to invert.
13235      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
13236      * @returns {Object} Returns the new inverted object.
13237      * @example
13238      *
13239      * var object = { 'a': 1, 'b': 2, 'c': 1 };
13240      *
13241      * _.invertBy(object);
13242      * // => { '1': ['a', 'c'], '2': ['b'] }
13243      *
13244      * _.invertBy(object, function(value) {
13245      *   return 'group' + value;
13246      * });
13247      * // => { 'group1': ['a', 'c'], 'group2': ['b'] }
13248      */
13249     var invertBy = createInverter(function(result, value, key) {
13250       if (hasOwnProperty.call(result, value)) {
13251         result[value].push(key);
13252       } else {
13253         result[value] = [key];
13254       }
13255     }, getIteratee);
13256
13257     /**
13258      * Invokes the method at `path` of `object`.
13259      *
13260      * @static
13261      * @memberOf _
13262      * @since 4.0.0
13263      * @category Object
13264      * @param {Object} object The object to query.
13265      * @param {Array|string} path The path of the method to invoke.
13266      * @param {...*} [args] The arguments to invoke the method with.
13267      * @returns {*} Returns the result of the invoked method.
13268      * @example
13269      *
13270      * var object = { 'a': [{ 'b': { 'c': [1, 2, 3, 4] } }] };
13271      *
13272      * _.invoke(object, 'a[0].b.c.slice', 1, 3);
13273      * // => [2, 3]
13274      */
13275     var invoke = baseRest(baseInvoke);
13276
13277     /**
13278      * Creates an array of the own enumerable property names of `object`.
13279      *
13280      * **Note:** Non-object values are coerced to objects. See the
13281      * [ES spec](http://ecma-international.org/ecma-262/7.0/#sec-object.keys)
13282      * for more details.
13283      *
13284      * @static
13285      * @since 0.1.0
13286      * @memberOf _
13287      * @category Object
13288      * @param {Object} object The object to query.
13289      * @returns {Array} Returns the array of property names.
13290      * @example
13291      *
13292      * function Foo() {
13293      *   this.a = 1;
13294      *   this.b = 2;
13295      * }
13296      *
13297      * Foo.prototype.c = 3;
13298      *
13299      * _.keys(new Foo);
13300      * // => ['a', 'b'] (iteration order is not guaranteed)
13301      *
13302      * _.keys('hi');
13303      * // => ['0', '1']
13304      */
13305     function keys(object) {
13306       return isArrayLike(object) ? arrayLikeKeys(object) : baseKeys(object);
13307     }
13308
13309     /**
13310      * Creates an array of the own and inherited enumerable property names of `object`.
13311      *
13312      * **Note:** Non-object values are coerced to objects.
13313      *
13314      * @static
13315      * @memberOf _
13316      * @since 3.0.0
13317      * @category Object
13318      * @param {Object} object The object to query.
13319      * @returns {Array} Returns the array of property names.
13320      * @example
13321      *
13322      * function Foo() {
13323      *   this.a = 1;
13324      *   this.b = 2;
13325      * }
13326      *
13327      * Foo.prototype.c = 3;
13328      *
13329      * _.keysIn(new Foo);
13330      * // => ['a', 'b', 'c'] (iteration order is not guaranteed)
13331      */
13332     function keysIn(object) {
13333       return isArrayLike(object) ? arrayLikeKeys(object, true) : baseKeysIn(object);
13334     }
13335
13336     /**
13337      * The opposite of `_.mapValues`; this method creates an object with the
13338      * same values as `object` and keys generated by running each own enumerable
13339      * string keyed property of `object` thru `iteratee`. The iteratee is invoked
13340      * with three arguments: (value, key, object).
13341      *
13342      * @static
13343      * @memberOf _
13344      * @since 3.8.0
13345      * @category Object
13346      * @param {Object} object The object to iterate over.
13347      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13348      * @returns {Object} Returns the new mapped object.
13349      * @see _.mapValues
13350      * @example
13351      *
13352      * _.mapKeys({ 'a': 1, 'b': 2 }, function(value, key) {
13353      *   return key + value;
13354      * });
13355      * // => { 'a1': 1, 'b2': 2 }
13356      */
13357     function mapKeys(object, iteratee) {
13358       var result = {};
13359       iteratee = getIteratee(iteratee, 3);
13360
13361       baseForOwn(object, function(value, key, object) {
13362         baseAssignValue(result, iteratee(value, key, object), value);
13363       });
13364       return result;
13365     }
13366
13367     /**
13368      * Creates an object with the same keys as `object` and values generated
13369      * by running each own enumerable string keyed property of `object` thru
13370      * `iteratee`. The iteratee is invoked with three arguments:
13371      * (value, key, object).
13372      *
13373      * @static
13374      * @memberOf _
13375      * @since 2.4.0
13376      * @category Object
13377      * @param {Object} object The object to iterate over.
13378      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13379      * @returns {Object} Returns the new mapped object.
13380      * @see _.mapKeys
13381      * @example
13382      *
13383      * var users = {
13384      *   'fred':    { 'user': 'fred',    'age': 40 },
13385      *   'pebbles': { 'user': 'pebbles', 'age': 1 }
13386      * };
13387      *
13388      * _.mapValues(users, function(o) { return o.age; });
13389      * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
13390      *
13391      * // The `_.property` iteratee shorthand.
13392      * _.mapValues(users, 'age');
13393      * // => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
13394      */
13395     function mapValues(object, iteratee) {
13396       var result = {};
13397       iteratee = getIteratee(iteratee, 3);
13398
13399       baseForOwn(object, function(value, key, object) {
13400         baseAssignValue(result, key, iteratee(value, key, object));
13401       });
13402       return result;
13403     }
13404
13405     /**
13406      * This method is like `_.assign` except that it recursively merges own and
13407      * inherited enumerable string keyed properties of source objects into the
13408      * destination object. Source properties that resolve to `undefined` are
13409      * skipped if a destination value exists. Array and plain object properties
13410      * are merged recursively. Other objects and value types are overridden by
13411      * assignment. Source objects are applied from left to right. Subsequent
13412      * sources overwrite property assignments of previous sources.
13413      *
13414      * **Note:** This method mutates `object`.
13415      *
13416      * @static
13417      * @memberOf _
13418      * @since 0.5.0
13419      * @category Object
13420      * @param {Object} object The destination object.
13421      * @param {...Object} [sources] The source objects.
13422      * @returns {Object} Returns `object`.
13423      * @example
13424      *
13425      * var object = {
13426      *   'a': [{ 'b': 2 }, { 'd': 4 }]
13427      * };
13428      *
13429      * var other = {
13430      *   'a': [{ 'c': 3 }, { 'e': 5 }]
13431      * };
13432      *
13433      * _.merge(object, other);
13434      * // => { 'a': [{ 'b': 2, 'c': 3 }, { 'd': 4, 'e': 5 }] }
13435      */
13436     var merge = createAssigner(function(object, source, srcIndex) {
13437       baseMerge(object, source, srcIndex);
13438     });
13439
13440     /**
13441      * This method is like `_.merge` except that it accepts `customizer` which
13442      * is invoked to produce the merged values of the destination and source
13443      * properties. If `customizer` returns `undefined`, merging is handled by the
13444      * method instead. The `customizer` is invoked with six arguments:
13445      * (objValue, srcValue, key, object, source, stack).
13446      *
13447      * **Note:** This method mutates `object`.
13448      *
13449      * @static
13450      * @memberOf _
13451      * @since 4.0.0
13452      * @category Object
13453      * @param {Object} object The destination object.
13454      * @param {...Object} sources The source objects.
13455      * @param {Function} customizer The function to customize assigned values.
13456      * @returns {Object} Returns `object`.
13457      * @example
13458      *
13459      * function customizer(objValue, srcValue) {
13460      *   if (_.isArray(objValue)) {
13461      *     return objValue.concat(srcValue);
13462      *   }
13463      * }
13464      *
13465      * var object = { 'a': [1], 'b': [2] };
13466      * var other = { 'a': [3], 'b': [4] };
13467      *
13468      * _.mergeWith(object, other, customizer);
13469      * // => { 'a': [1, 3], 'b': [2, 4] }
13470      */
13471     var mergeWith = createAssigner(function(object, source, srcIndex, customizer) {
13472       baseMerge(object, source, srcIndex, customizer);
13473     });
13474
13475     /**
13476      * The opposite of `_.pick`; this method creates an object composed of the
13477      * own and inherited enumerable property paths of `object` that are not omitted.
13478      *
13479      * **Note:** This method is considerably slower than `_.pick`.
13480      *
13481      * @static
13482      * @since 0.1.0
13483      * @memberOf _
13484      * @category Object
13485      * @param {Object} object The source object.
13486      * @param {...(string|string[])} [paths] The property paths to omit.
13487      * @returns {Object} Returns the new object.
13488      * @example
13489      *
13490      * var object = { 'a': 1, 'b': '2', 'c': 3 };
13491      *
13492      * _.omit(object, ['a', 'c']);
13493      * // => { 'b': '2' }
13494      */
13495     var omit = flatRest(function(object, paths) {
13496       var result = {};
13497       if (object == null) {
13498         return result;
13499       }
13500       copyObject(object, getAllKeysIn(object), result);
13501       result = baseClone(result, CLONE_DEEP_FLAG | CLONE_FLAT_FLAG | CLONE_SYMBOLS_FLAG);
13502
13503       var length = paths.length;
13504       while (length--) {
13505         baseUnset(result, paths[length]);
13506       }
13507       return result;
13508     });
13509
13510     /**
13511      * The opposite of `_.pickBy`; this method creates an object composed of
13512      * the own and inherited enumerable string keyed properties of `object` that
13513      * `predicate` doesn't return truthy for. The predicate is invoked with two
13514      * arguments: (value, key).
13515      *
13516      * @static
13517      * @memberOf _
13518      * @since 4.0.0
13519      * @category Object
13520      * @param {Object} object The source object.
13521      * @param {Function} [predicate=_.identity] The function invoked per property.
13522      * @returns {Object} Returns the new object.
13523      * @example
13524      *
13525      * var object = { 'a': 1, 'b': '2', 'c': 3 };
13526      *
13527      * _.omitBy(object, _.isNumber);
13528      * // => { 'b': '2' }
13529      */
13530     function omitBy(object, predicate) {
13531       return pickBy(object, negate(getIteratee(predicate)));
13532     }
13533
13534     /**
13535      * Creates an object composed of the picked `object` properties.
13536      *
13537      * @static
13538      * @since 0.1.0
13539      * @memberOf _
13540      * @category Object
13541      * @param {Object} object The source object.
13542      * @param {...(string|string[])} [paths] The property paths to pick.
13543      * @returns {Object} Returns the new object.
13544      * @example
13545      *
13546      * var object = { 'a': 1, 'b': '2', 'c': 3 };
13547      *
13548      * _.pick(object, ['a', 'c']);
13549      * // => { 'a': 1, 'c': 3 }
13550      */
13551     var pick = flatRest(function(object, paths) {
13552       return object == null ? {} : basePick(object, arrayMap(paths, toKey));
13553     });
13554
13555     /**
13556      * Creates an object composed of the `object` properties `predicate` returns
13557      * truthy for. The predicate is invoked with two arguments: (value, key).
13558      *
13559      * @static
13560      * @memberOf _
13561      * @since 4.0.0
13562      * @category Object
13563      * @param {Object} object The source object.
13564      * @param {Function} [predicate=_.identity] The function invoked per property.
13565      * @returns {Object} Returns the new object.
13566      * @example
13567      *
13568      * var object = { 'a': 1, 'b': '2', 'c': 3 };
13569      *
13570      * _.pickBy(object, _.isNumber);
13571      * // => { 'a': 1, 'c': 3 }
13572      */
13573     function pickBy(object, predicate) {
13574       return object == null ? {} : basePickBy(object, getAllKeysIn(object), getIteratee(predicate));
13575     }
13576
13577     /**
13578      * This method is like `_.get` except that if the resolved value is a
13579      * function it's invoked with the `this` binding of its parent object and
13580      * its result is returned.
13581      *
13582      * @static
13583      * @since 0.1.0
13584      * @memberOf _
13585      * @category Object
13586      * @param {Object} object The object to query.
13587      * @param {Array|string} path The path of the property to resolve.
13588      * @param {*} [defaultValue] The value returned for `undefined` resolved values.
13589      * @returns {*} Returns the resolved value.
13590      * @example
13591      *
13592      * var object = { 'a': [{ 'b': { 'c1': 3, 'c2': _.constant(4) } }] };
13593      *
13594      * _.result(object, 'a[0].b.c1');
13595      * // => 3
13596      *
13597      * _.result(object, 'a[0].b.c2');
13598      * // => 4
13599      *
13600      * _.result(object, 'a[0].b.c3', 'default');
13601      * // => 'default'
13602      *
13603      * _.result(object, 'a[0].b.c3', _.constant('default'));
13604      * // => 'default'
13605      */
13606     function result(object, path, defaultValue) {
13607       path = isKey(path, object) ? [path] : castPath(path);
13608
13609       var index = -1,
13610           length = path.length;
13611
13612       // Ensure the loop is entered when path is empty.
13613       if (!length) {
13614         object = undefined;
13615         length = 1;
13616       }
13617       while (++index < length) {
13618         var value = object == null ? undefined : object[toKey(path[index])];
13619         if (value === undefined) {
13620           index = length;
13621           value = defaultValue;
13622         }
13623         object = isFunction(value) ? value.call(object) : value;
13624       }
13625       return object;
13626     }
13627
13628     /**
13629      * Sets the value at `path` of `object`. If a portion of `path` doesn't exist,
13630      * it's created. Arrays are created for missing index properties while objects
13631      * are created for all other missing properties. Use `_.setWith` to customize
13632      * `path` creation.
13633      *
13634      * **Note:** This method mutates `object`.
13635      *
13636      * @static
13637      * @memberOf _
13638      * @since 3.7.0
13639      * @category Object
13640      * @param {Object} object The object to modify.
13641      * @param {Array|string} path The path of the property to set.
13642      * @param {*} value The value to set.
13643      * @returns {Object} Returns `object`.
13644      * @example
13645      *
13646      * var object = { 'a': [{ 'b': { 'c': 3 } }] };
13647      *
13648      * _.set(object, 'a[0].b.c', 4);
13649      * console.log(object.a[0].b.c);
13650      * // => 4
13651      *
13652      * _.set(object, ['x', '0', 'y', 'z'], 5);
13653      * console.log(object.x[0].y.z);
13654      * // => 5
13655      */
13656     function set(object, path, value) {
13657       return object == null ? object : baseSet(object, path, value);
13658     }
13659
13660     /**
13661      * This method is like `_.set` except that it accepts `customizer` which is
13662      * invoked to produce the objects of `path`.  If `customizer` returns `undefined`
13663      * path creation is handled by the method instead. The `customizer` is invoked
13664      * with three arguments: (nsValue, key, nsObject).
13665      *
13666      * **Note:** This method mutates `object`.
13667      *
13668      * @static
13669      * @memberOf _
13670      * @since 4.0.0
13671      * @category Object
13672      * @param {Object} object The object to modify.
13673      * @param {Array|string} path The path of the property to set.
13674      * @param {*} value The value to set.
13675      * @param {Function} [customizer] The function to customize assigned values.
13676      * @returns {Object} Returns `object`.
13677      * @example
13678      *
13679      * var object = {};
13680      *
13681      * _.setWith(object, '[0][1]', 'a', Object);
13682      * // => { '0': { '1': 'a' } }
13683      */
13684     function setWith(object, path, value, customizer) {
13685       customizer = typeof customizer == 'function' ? customizer : undefined;
13686       return object == null ? object : baseSet(object, path, value, customizer);
13687     }
13688
13689     /**
13690      * Creates an array of own enumerable string keyed-value pairs for `object`
13691      * which can be consumed by `_.fromPairs`. If `object` is a map or set, its
13692      * entries are returned.
13693      *
13694      * @static
13695      * @memberOf _
13696      * @since 4.0.0
13697      * @alias entries
13698      * @category Object
13699      * @param {Object} object The object to query.
13700      * @returns {Array} Returns the key-value pairs.
13701      * @example
13702      *
13703      * function Foo() {
13704      *   this.a = 1;
13705      *   this.b = 2;
13706      * }
13707      *
13708      * Foo.prototype.c = 3;
13709      *
13710      * _.toPairs(new Foo);
13711      * // => [['a', 1], ['b', 2]] (iteration order is not guaranteed)
13712      */
13713     var toPairs = createToPairs(keys);
13714
13715     /**
13716      * Creates an array of own and inherited enumerable string keyed-value pairs
13717      * for `object` which can be consumed by `_.fromPairs`. If `object` is a map
13718      * or set, its entries are returned.
13719      *
13720      * @static
13721      * @memberOf _
13722      * @since 4.0.0
13723      * @alias entriesIn
13724      * @category Object
13725      * @param {Object} object The object to query.
13726      * @returns {Array} Returns the key-value pairs.
13727      * @example
13728      *
13729      * function Foo() {
13730      *   this.a = 1;
13731      *   this.b = 2;
13732      * }
13733      *
13734      * Foo.prototype.c = 3;
13735      *
13736      * _.toPairsIn(new Foo);
13737      * // => [['a', 1], ['b', 2], ['c', 3]] (iteration order is not guaranteed)
13738      */
13739     var toPairsIn = createToPairs(keysIn);
13740
13741     /**
13742      * An alternative to `_.reduce`; this method transforms `object` to a new
13743      * `accumulator` object which is the result of running each of its own
13744      * enumerable string keyed properties thru `iteratee`, with each invocation
13745      * potentially mutating the `accumulator` object. If `accumulator` is not
13746      * provided, a new object with the same `[[Prototype]]` will be used. The
13747      * iteratee is invoked with four arguments: (accumulator, value, key, object).
13748      * Iteratee functions may exit iteration early by explicitly returning `false`.
13749      *
13750      * @static
13751      * @memberOf _
13752      * @since 1.3.0
13753      * @category Object
13754      * @param {Object} object The object to iterate over.
13755      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
13756      * @param {*} [accumulator] The custom accumulator value.
13757      * @returns {*} Returns the accumulated value.
13758      * @example
13759      *
13760      * _.transform([2, 3, 4], function(result, n) {
13761      *   result.push(n *= n);
13762      *   return n % 2 == 0;
13763      * }, []);
13764      * // => [4, 9]
13765      *
13766      * _.transform({ 'a': 1, 'b': 2, 'c': 1 }, function(result, value, key) {
13767      *   (result[value] || (result[value] = [])).push(key);
13768      * }, {});
13769      * // => { '1': ['a', 'c'], '2': ['b'] }
13770      */
13771     function transform(object, iteratee, accumulator) {
13772       var isArr = isArray(object),
13773           isArrLike = isArr || isBuffer(object) || isTypedArray(object);
13774
13775       iteratee = getIteratee(iteratee, 4);
13776       if (accumulator == null) {
13777         var Ctor = object && object.constructor;
13778         if (isArrLike) {
13779           accumulator = isArr ? new Ctor : [];
13780         }
13781         else if (isObject(object)) {
13782           accumulator = isFunction(Ctor) ? baseCreate(getPrototype(object)) : {};
13783         }
13784         else {
13785           accumulator = {};
13786         }
13787       }
13788       (isArrLike ? arrayEach : baseForOwn)(object, function(value, index, object) {
13789         return iteratee(accumulator, value, index, object);
13790       });
13791       return accumulator;
13792     }
13793
13794     /**
13795      * Removes the property at `path` of `object`.
13796      *
13797      * **Note:** This method mutates `object`.
13798      *
13799      * @static
13800      * @memberOf _
13801      * @since 4.0.0
13802      * @category Object
13803      * @param {Object} object The object to modify.
13804      * @param {Array|string} path The path of the property to unset.
13805      * @returns {boolean} Returns `true` if the property is deleted, else `false`.
13806      * @example
13807      *
13808      * var object = { 'a': [{ 'b': { 'c': 7 } }] };
13809      * _.unset(object, 'a[0].b.c');
13810      * // => true
13811      *
13812      * console.log(object);
13813      * // => { 'a': [{ 'b': {} }] };
13814      *
13815      * _.unset(object, ['a', '0', 'b', 'c']);
13816      * // => true
13817      *
13818      * console.log(object);
13819      * // => { 'a': [{ 'b': {} }] };
13820      */
13821     function unset(object, path) {
13822       return object == null ? true : baseUnset(object, path);
13823     }
13824
13825     /**
13826      * This method is like `_.set` except that accepts `updater` to produce the
13827      * value to set. Use `_.updateWith` to customize `path` creation. The `updater`
13828      * is invoked with one argument: (value).
13829      *
13830      * **Note:** This method mutates `object`.
13831      *
13832      * @static
13833      * @memberOf _
13834      * @since 4.6.0
13835      * @category Object
13836      * @param {Object} object The object to modify.
13837      * @param {Array|string} path The path of the property to set.
13838      * @param {Function} updater The function to produce the updated value.
13839      * @returns {Object} Returns `object`.
13840      * @example
13841      *
13842      * var object = { 'a': [{ 'b': { 'c': 3 } }] };
13843      *
13844      * _.update(object, 'a[0].b.c', function(n) { return n * n; });
13845      * console.log(object.a[0].b.c);
13846      * // => 9
13847      *
13848      * _.update(object, 'x[0].y.z', function(n) { return n ? n + 1 : 0; });
13849      * console.log(object.x[0].y.z);
13850      * // => 0
13851      */
13852     function update(object, path, updater) {
13853       return object == null ? object : baseUpdate(object, path, castFunction(updater));
13854     }
13855
13856     /**
13857      * This method is like `_.update` except that it accepts `customizer` which is
13858      * invoked to produce the objects of `path`.  If `customizer` returns `undefined`
13859      * path creation is handled by the method instead. The `customizer` is invoked
13860      * with three arguments: (nsValue, key, nsObject).
13861      *
13862      * **Note:** This method mutates `object`.
13863      *
13864      * @static
13865      * @memberOf _
13866      * @since 4.6.0
13867      * @category Object
13868      * @param {Object} object The object to modify.
13869      * @param {Array|string} path The path of the property to set.
13870      * @param {Function} updater The function to produce the updated value.
13871      * @param {Function} [customizer] The function to customize assigned values.
13872      * @returns {Object} Returns `object`.
13873      * @example
13874      *
13875      * var object = {};
13876      *
13877      * _.updateWith(object, '[0][1]', _.constant('a'), Object);
13878      * // => { '0': { '1': 'a' } }
13879      */
13880     function updateWith(object, path, updater, customizer) {
13881       customizer = typeof customizer == 'function' ? customizer : undefined;
13882       return object == null ? object : baseUpdate(object, path, castFunction(updater), customizer);
13883     }
13884
13885     /**
13886      * Creates an array of the own enumerable string keyed property values of `object`.
13887      *
13888      * **Note:** Non-object values are coerced to objects.
13889      *
13890      * @static
13891      * @since 0.1.0
13892      * @memberOf _
13893      * @category Object
13894      * @param {Object} object The object to query.
13895      * @returns {Array} Returns the array of property values.
13896      * @example
13897      *
13898      * function Foo() {
13899      *   this.a = 1;
13900      *   this.b = 2;
13901      * }
13902      *
13903      * Foo.prototype.c = 3;
13904      *
13905      * _.values(new Foo);
13906      * // => [1, 2] (iteration order is not guaranteed)
13907      *
13908      * _.values('hi');
13909      * // => ['h', 'i']
13910      */
13911     function values(object) {
13912       return object == null ? [] : baseValues(object, keys(object));
13913     }
13914
13915     /**
13916      * Creates an array of the own and inherited enumerable string keyed property
13917      * values of `object`.
13918      *
13919      * **Note:** Non-object values are coerced to objects.
13920      *
13921      * @static
13922      * @memberOf _
13923      * @since 3.0.0
13924      * @category Object
13925      * @param {Object} object The object to query.
13926      * @returns {Array} Returns the array of property values.
13927      * @example
13928      *
13929      * function Foo() {
13930      *   this.a = 1;
13931      *   this.b = 2;
13932      * }
13933      *
13934      * Foo.prototype.c = 3;
13935      *
13936      * _.valuesIn(new Foo);
13937      * // => [1, 2, 3] (iteration order is not guaranteed)
13938      */
13939     function valuesIn(object) {
13940       return object == null ? [] : baseValues(object, keysIn(object));
13941     }
13942
13943     /*------------------------------------------------------------------------*/
13944
13945     /**
13946      * Clamps `number` within the inclusive `lower` and `upper` bounds.
13947      *
13948      * @static
13949      * @memberOf _
13950      * @since 4.0.0
13951      * @category Number
13952      * @param {number} number The number to clamp.
13953      * @param {number} [lower] The lower bound.
13954      * @param {number} upper The upper bound.
13955      * @returns {number} Returns the clamped number.
13956      * @example
13957      *
13958      * _.clamp(-10, -5, 5);
13959      * // => -5
13960      *
13961      * _.clamp(10, -5, 5);
13962      * // => 5
13963      */
13964     function clamp(number, lower, upper) {
13965       if (upper === undefined) {
13966         upper = lower;
13967         lower = undefined;
13968       }
13969       if (upper !== undefined) {
13970         upper = toNumber(upper);
13971         upper = upper === upper ? upper : 0;
13972       }
13973       if (lower !== undefined) {
13974         lower = toNumber(lower);
13975         lower = lower === lower ? lower : 0;
13976       }
13977       return baseClamp(toNumber(number), lower, upper);
13978     }
13979
13980     /**
13981      * Checks if `n` is between `start` and up to, but not including, `end`. If
13982      * `end` is not specified, it's set to `start` with `start` then set to `0`.
13983      * If `start` is greater than `end` the params are swapped to support
13984      * negative ranges.
13985      *
13986      * @static
13987      * @memberOf _
13988      * @since 3.3.0
13989      * @category Number
13990      * @param {number} number The number to check.
13991      * @param {number} [start=0] The start of the range.
13992      * @param {number} end The end of the range.
13993      * @returns {boolean} Returns `true` if `number` is in the range, else `false`.
13994      * @see _.range, _.rangeRight
13995      * @example
13996      *
13997      * _.inRange(3, 2, 4);
13998      * // => true
13999      *
14000      * _.inRange(4, 8);
14001      * // => true
14002      *
14003      * _.inRange(4, 2);
14004      * // => false
14005      *
14006      * _.inRange(2, 2);
14007      * // => false
14008      *
14009      * _.inRange(1.2, 2);
14010      * // => true
14011      *
14012      * _.inRange(5.2, 4);
14013      * // => false
14014      *
14015      * _.inRange(-3, -2, -6);
14016      * // => true
14017      */
14018     function inRange(number, start, end) {
14019       start = toFinite(start);
14020       if (end === undefined) {
14021         end = start;
14022         start = 0;
14023       } else {
14024         end = toFinite(end);
14025       }
14026       number = toNumber(number);
14027       return baseInRange(number, start, end);
14028     }
14029
14030     /**
14031      * Produces a random number between the inclusive `lower` and `upper` bounds.
14032      * If only one argument is provided a number between `0` and the given number
14033      * is returned. If `floating` is `true`, or either `lower` or `upper` are
14034      * floats, a floating-point number is returned instead of an integer.
14035      *
14036      * **Note:** JavaScript follows the IEEE-754 standard for resolving
14037      * floating-point values which can produce unexpected results.
14038      *
14039      * @static
14040      * @memberOf _
14041      * @since 0.7.0
14042      * @category Number
14043      * @param {number} [lower=0] The lower bound.
14044      * @param {number} [upper=1] The upper bound.
14045      * @param {boolean} [floating] Specify returning a floating-point number.
14046      * @returns {number} Returns the random number.
14047      * @example
14048      *
14049      * _.random(0, 5);
14050      * // => an integer between 0 and 5
14051      *
14052      * _.random(5);
14053      * // => also an integer between 0 and 5
14054      *
14055      * _.random(5, true);
14056      * // => a floating-point number between 0 and 5
14057      *
14058      * _.random(1.2, 5.2);
14059      * // => a floating-point number between 1.2 and 5.2
14060      */
14061     function random(lower, upper, floating) {
14062       if (floating && typeof floating != 'boolean' && isIterateeCall(lower, upper, floating)) {
14063         upper = floating = undefined;
14064       }
14065       if (floating === undefined) {
14066         if (typeof upper == 'boolean') {
14067           floating = upper;
14068           upper = undefined;
14069         }
14070         else if (typeof lower == 'boolean') {
14071           floating = lower;
14072           lower = undefined;
14073         }
14074       }
14075       if (lower === undefined && upper === undefined) {
14076         lower = 0;
14077         upper = 1;
14078       }
14079       else {
14080         lower = toFinite(lower);
14081         if (upper === undefined) {
14082           upper = lower;
14083           lower = 0;
14084         } else {
14085           upper = toFinite(upper);
14086         }
14087       }
14088       if (lower > upper) {
14089         var temp = lower;
14090         lower = upper;
14091         upper = temp;
14092       }
14093       if (floating || lower % 1 || upper % 1) {
14094         var rand = nativeRandom();
14095         return nativeMin(lower + (rand * (upper - lower + freeParseFloat('1e-' + ((rand + '').length - 1)))), upper);
14096       }
14097       return baseRandom(lower, upper);
14098     }
14099
14100     /*------------------------------------------------------------------------*/
14101
14102     /**
14103      * Converts `string` to [camel case](https://en.wikipedia.org/wiki/CamelCase).
14104      *
14105      * @static
14106      * @memberOf _
14107      * @since 3.0.0
14108      * @category String
14109      * @param {string} [string=''] The string to convert.
14110      * @returns {string} Returns the camel cased string.
14111      * @example
14112      *
14113      * _.camelCase('Foo Bar');
14114      * // => 'fooBar'
14115      *
14116      * _.camelCase('--foo-bar--');
14117      * // => 'fooBar'
14118      *
14119      * _.camelCase('__FOO_BAR__');
14120      * // => 'fooBar'
14121      */
14122     var camelCase = createCompounder(function(result, word, index) {
14123       word = word.toLowerCase();
14124       return result + (index ? capitalize(word) : word);
14125     });
14126
14127     /**
14128      * Converts the first character of `string` to upper case and the remaining
14129      * to lower case.
14130      *
14131      * @static
14132      * @memberOf _
14133      * @since 3.0.0
14134      * @category String
14135      * @param {string} [string=''] The string to capitalize.
14136      * @returns {string} Returns the capitalized string.
14137      * @example
14138      *
14139      * _.capitalize('FRED');
14140      * // => 'Fred'
14141      */
14142     function capitalize(string) {
14143       return upperFirst(toString(string).toLowerCase());
14144     }
14145
14146     /**
14147      * Deburrs `string` by converting
14148      * [Latin-1 Supplement](https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)#Character_table)
14149      * and [Latin Extended-A](https://en.wikipedia.org/wiki/Latin_Extended-A)
14150      * letters to basic Latin letters and removing
14151      * [combining diacritical marks](https://en.wikipedia.org/wiki/Combining_Diacritical_Marks).
14152      *
14153      * @static
14154      * @memberOf _
14155      * @since 3.0.0
14156      * @category String
14157      * @param {string} [string=''] The string to deburr.
14158      * @returns {string} Returns the deburred string.
14159      * @example
14160      *
14161      * _.deburr('déjà vu');
14162      * // => 'deja vu'
14163      */
14164     function deburr(string) {
14165       string = toString(string);
14166       return string && string.replace(reLatin, deburrLetter).replace(reComboMark, '');
14167     }
14168
14169     /**
14170      * Checks if `string` ends with the given target string.
14171      *
14172      * @static
14173      * @memberOf _
14174      * @since 3.0.0
14175      * @category String
14176      * @param {string} [string=''] The string to inspect.
14177      * @param {string} [target] The string to search for.
14178      * @param {number} [position=string.length] The position to search up to.
14179      * @returns {boolean} Returns `true` if `string` ends with `target`,
14180      *  else `false`.
14181      * @example
14182      *
14183      * _.endsWith('abc', 'c');
14184      * // => true
14185      *
14186      * _.endsWith('abc', 'b');
14187      * // => false
14188      *
14189      * _.endsWith('abc', 'b', 2);
14190      * // => true
14191      */
14192     function endsWith(string, target, position) {
14193       string = toString(string);
14194       target = baseToString(target);
14195
14196       var length = string.length;
14197       position = position === undefined
14198         ? length
14199         : baseClamp(toInteger(position), 0, length);
14200
14201       var end = position;
14202       position -= target.length;
14203       return position >= 0 && string.slice(position, end) == target;
14204     }
14205
14206     /**
14207      * Converts the characters "&", "<", ">", '"', and "'" in `string` to their
14208      * corresponding HTML entities.
14209      *
14210      * **Note:** No other characters are escaped. To escape additional
14211      * characters use a third-party library like [_he_](https://mths.be/he).
14212      *
14213      * Though the ">" character is escaped for symmetry, characters like
14214      * ">" and "/" don't need escaping in HTML and have no special meaning
14215      * unless they're part of a tag or unquoted attribute value. See
14216      * [Mathias Bynens's article](https://mathiasbynens.be/notes/ambiguous-ampersands)
14217      * (under "semi-related fun fact") for more details.
14218      *
14219      * When working with HTML you should always
14220      * [quote attribute values](http://wonko.com/post/html-escaping) to reduce
14221      * XSS vectors.
14222      *
14223      * @static
14224      * @since 0.1.0
14225      * @memberOf _
14226      * @category String
14227      * @param {string} [string=''] The string to escape.
14228      * @returns {string} Returns the escaped string.
14229      * @example
14230      *
14231      * _.escape('fred, barney, & pebbles');
14232      * // => 'fred, barney, &amp; pebbles'
14233      */
14234     function escape(string) {
14235       string = toString(string);
14236       return (string && reHasUnescapedHtml.test(string))
14237         ? string.replace(reUnescapedHtml, escapeHtmlChar)
14238         : string;
14239     }
14240
14241     /**
14242      * Escapes the `RegExp` special characters "^", "$", "\", ".", "*", "+",
14243      * "?", "(", ")", "[", "]", "{", "}", and "|" in `string`.
14244      *
14245      * @static
14246      * @memberOf _
14247      * @since 3.0.0
14248      * @category String
14249      * @param {string} [string=''] The string to escape.
14250      * @returns {string} Returns the escaped string.
14251      * @example
14252      *
14253      * _.escapeRegExp('[lodash](https://lodash.com/)');
14254      * // => '\[lodash\]\(https://lodash\.com/\)'
14255      */
14256     function escapeRegExp(string) {
14257       string = toString(string);
14258       return (string && reHasRegExpChar.test(string))
14259         ? string.replace(reRegExpChar, '\\$&')
14260         : string;
14261     }
14262
14263     /**
14264      * Converts `string` to
14265      * [kebab case](https://en.wikipedia.org/wiki/Letter_case#Special_case_styles).
14266      *
14267      * @static
14268      * @memberOf _
14269      * @since 3.0.0
14270      * @category String
14271      * @param {string} [string=''] The string to convert.
14272      * @returns {string} Returns the kebab cased string.
14273      * @example
14274      *
14275      * _.kebabCase('Foo Bar');
14276      * // => 'foo-bar'
14277      *
14278      * _.kebabCase('fooBar');
14279      * // => 'foo-bar'
14280      *
14281      * _.kebabCase('__FOO_BAR__');
14282      * // => 'foo-bar'
14283      */
14284     var kebabCase = createCompounder(function(result, word, index) {
14285       return result + (index ? '-' : '') + word.toLowerCase();
14286     });
14287
14288     /**
14289      * Converts `string`, as space separated words, to lower case.
14290      *
14291      * @static
14292      * @memberOf _
14293      * @since 4.0.0
14294      * @category String
14295      * @param {string} [string=''] The string to convert.
14296      * @returns {string} Returns the lower cased string.
14297      * @example
14298      *
14299      * _.lowerCase('--Foo-Bar--');
14300      * // => 'foo bar'
14301      *
14302      * _.lowerCase('fooBar');
14303      * // => 'foo bar'
14304      *
14305      * _.lowerCase('__FOO_BAR__');
14306      * // => 'foo bar'
14307      */
14308     var lowerCase = createCompounder(function(result, word, index) {
14309       return result + (index ? ' ' : '') + word.toLowerCase();
14310     });
14311
14312     /**
14313      * Converts the first character of `string` to lower case.
14314      *
14315      * @static
14316      * @memberOf _
14317      * @since 4.0.0
14318      * @category String
14319      * @param {string} [string=''] The string to convert.
14320      * @returns {string} Returns the converted string.
14321      * @example
14322      *
14323      * _.lowerFirst('Fred');
14324      * // => 'fred'
14325      *
14326      * _.lowerFirst('FRED');
14327      * // => 'fRED'
14328      */
14329     var lowerFirst = createCaseFirst('toLowerCase');
14330
14331     /**
14332      * Pads `string` on the left and right sides if it's shorter than `length`.
14333      * Padding characters are truncated if they can't be evenly divided by `length`.
14334      *
14335      * @static
14336      * @memberOf _
14337      * @since 3.0.0
14338      * @category String
14339      * @param {string} [string=''] The string to pad.
14340      * @param {number} [length=0] The padding length.
14341      * @param {string} [chars=' '] The string used as padding.
14342      * @returns {string} Returns the padded string.
14343      * @example
14344      *
14345      * _.pad('abc', 8);
14346      * // => '  abc   '
14347      *
14348      * _.pad('abc', 8, '_-');
14349      * // => '_-abc_-_'
14350      *
14351      * _.pad('abc', 3);
14352      * // => 'abc'
14353      */
14354     function pad(string, length, chars) {
14355       string = toString(string);
14356       length = toInteger(length);
14357
14358       var strLength = length ? stringSize(string) : 0;
14359       if (!length || strLength >= length) {
14360         return string;
14361       }
14362       var mid = (length - strLength) / 2;
14363       return (
14364         createPadding(nativeFloor(mid), chars) +
14365         string +
14366         createPadding(nativeCeil(mid), chars)
14367       );
14368     }
14369
14370     /**
14371      * Pads `string` on the right side if it's shorter than `length`. Padding
14372      * characters are truncated if they exceed `length`.
14373      *
14374      * @static
14375      * @memberOf _
14376      * @since 4.0.0
14377      * @category String
14378      * @param {string} [string=''] The string to pad.
14379      * @param {number} [length=0] The padding length.
14380      * @param {string} [chars=' '] The string used as padding.
14381      * @returns {string} Returns the padded string.
14382      * @example
14383      *
14384      * _.padEnd('abc', 6);
14385      * // => 'abc   '
14386      *
14387      * _.padEnd('abc', 6, '_-');
14388      * // => 'abc_-_'
14389      *
14390      * _.padEnd('abc', 3);
14391      * // => 'abc'
14392      */
14393     function padEnd(string, length, chars) {
14394       string = toString(string);
14395       length = toInteger(length);
14396
14397       var strLength = length ? stringSize(string) : 0;
14398       return (length && strLength < length)
14399         ? (string + createPadding(length - strLength, chars))
14400         : string;
14401     }
14402
14403     /**
14404      * Pads `string` on the left side if it's shorter than `length`. Padding
14405      * characters are truncated if they exceed `length`.
14406      *
14407      * @static
14408      * @memberOf _
14409      * @since 4.0.0
14410      * @category String
14411      * @param {string} [string=''] The string to pad.
14412      * @param {number} [length=0] The padding length.
14413      * @param {string} [chars=' '] The string used as padding.
14414      * @returns {string} Returns the padded string.
14415      * @example
14416      *
14417      * _.padStart('abc', 6);
14418      * // => '   abc'
14419      *
14420      * _.padStart('abc', 6, '_-');
14421      * // => '_-_abc'
14422      *
14423      * _.padStart('abc', 3);
14424      * // => 'abc'
14425      */
14426     function padStart(string, length, chars) {
14427       string = toString(string);
14428       length = toInteger(length);
14429
14430       var strLength = length ? stringSize(string) : 0;
14431       return (length && strLength < length)
14432         ? (createPadding(length - strLength, chars) + string)
14433         : string;
14434     }
14435
14436     /**
14437      * Converts `string` to an integer of the specified radix. If `radix` is
14438      * `undefined` or `0`, a `radix` of `10` is used unless `value` is a
14439      * hexadecimal, in which case a `radix` of `16` is used.
14440      *
14441      * **Note:** This method aligns with the
14442      * [ES5 implementation](https://es5.github.io/#x15.1.2.2) of `parseInt`.
14443      *
14444      * @static
14445      * @memberOf _
14446      * @since 1.1.0
14447      * @category String
14448      * @param {string} string The string to convert.
14449      * @param {number} [radix=10] The radix to interpret `value` by.
14450      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14451      * @returns {number} Returns the converted integer.
14452      * @example
14453      *
14454      * _.parseInt('08');
14455      * // => 8
14456      *
14457      * _.map(['6', '08', '10'], _.parseInt);
14458      * // => [6, 8, 10]
14459      */
14460     function parseInt(string, radix, guard) {
14461       if (guard || radix == null) {
14462         radix = 0;
14463       } else if (radix) {
14464         radix = +radix;
14465       }
14466       return nativeParseInt(toString(string).replace(reTrimStart, ''), radix || 0);
14467     }
14468
14469     /**
14470      * Repeats the given string `n` times.
14471      *
14472      * @static
14473      * @memberOf _
14474      * @since 3.0.0
14475      * @category String
14476      * @param {string} [string=''] The string to repeat.
14477      * @param {number} [n=1] The number of times to repeat the string.
14478      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14479      * @returns {string} Returns the repeated string.
14480      * @example
14481      *
14482      * _.repeat('*', 3);
14483      * // => '***'
14484      *
14485      * _.repeat('abc', 2);
14486      * // => 'abcabc'
14487      *
14488      * _.repeat('abc', 0);
14489      * // => ''
14490      */
14491     function repeat(string, n, guard) {
14492       if ((guard ? isIterateeCall(string, n, guard) : n === undefined)) {
14493         n = 1;
14494       } else {
14495         n = toInteger(n);
14496       }
14497       return baseRepeat(toString(string), n);
14498     }
14499
14500     /**
14501      * Replaces matches for `pattern` in `string` with `replacement`.
14502      *
14503      * **Note:** This method is based on
14504      * [`String#replace`](https://mdn.io/String/replace).
14505      *
14506      * @static
14507      * @memberOf _
14508      * @since 4.0.0
14509      * @category String
14510      * @param {string} [string=''] The string to modify.
14511      * @param {RegExp|string} pattern The pattern to replace.
14512      * @param {Function|string} replacement The match replacement.
14513      * @returns {string} Returns the modified string.
14514      * @example
14515      *
14516      * _.replace('Hi Fred', 'Fred', 'Barney');
14517      * // => 'Hi Barney'
14518      */
14519     function replace() {
14520       var args = arguments,
14521           string = toString(args[0]);
14522
14523       return args.length < 3 ? string : string.replace(args[1], args[2]);
14524     }
14525
14526     /**
14527      * Converts `string` to
14528      * [snake case](https://en.wikipedia.org/wiki/Snake_case).
14529      *
14530      * @static
14531      * @memberOf _
14532      * @since 3.0.0
14533      * @category String
14534      * @param {string} [string=''] The string to convert.
14535      * @returns {string} Returns the snake cased string.
14536      * @example
14537      *
14538      * _.snakeCase('Foo Bar');
14539      * // => 'foo_bar'
14540      *
14541      * _.snakeCase('fooBar');
14542      * // => 'foo_bar'
14543      *
14544      * _.snakeCase('--FOO-BAR--');
14545      * // => 'foo_bar'
14546      */
14547     var snakeCase = createCompounder(function(result, word, index) {
14548       return result + (index ? '_' : '') + word.toLowerCase();
14549     });
14550
14551     /**
14552      * Splits `string` by `separator`.
14553      *
14554      * **Note:** This method is based on
14555      * [`String#split`](https://mdn.io/String/split).
14556      *
14557      * @static
14558      * @memberOf _
14559      * @since 4.0.0
14560      * @category String
14561      * @param {string} [string=''] The string to split.
14562      * @param {RegExp|string} separator The separator pattern to split by.
14563      * @param {number} [limit] The length to truncate results to.
14564      * @returns {Array} Returns the string segments.
14565      * @example
14566      *
14567      * _.split('a-b-c', '-', 2);
14568      * // => ['a', 'b']
14569      */
14570     function split(string, separator, limit) {
14571       if (limit && typeof limit != 'number' && isIterateeCall(string, separator, limit)) {
14572         separator = limit = undefined;
14573       }
14574       limit = limit === undefined ? MAX_ARRAY_LENGTH : limit >>> 0;
14575       if (!limit) {
14576         return [];
14577       }
14578       string = toString(string);
14579       if (string && (
14580             typeof separator == 'string' ||
14581             (separator != null && !isRegExp(separator))
14582           )) {
14583         separator = baseToString(separator);
14584         if (!separator && hasUnicode(string)) {
14585           return castSlice(stringToArray(string), 0, limit);
14586         }
14587       }
14588       return string.split(separator, limit);
14589     }
14590
14591     /**
14592      * Converts `string` to
14593      * [start case](https://en.wikipedia.org/wiki/Letter_case#Stylistic_or_specialised_usage).
14594      *
14595      * @static
14596      * @memberOf _
14597      * @since 3.1.0
14598      * @category String
14599      * @param {string} [string=''] The string to convert.
14600      * @returns {string} Returns the start cased string.
14601      * @example
14602      *
14603      * _.startCase('--foo-bar--');
14604      * // => 'Foo Bar'
14605      *
14606      * _.startCase('fooBar');
14607      * // => 'Foo Bar'
14608      *
14609      * _.startCase('__FOO_BAR__');
14610      * // => 'FOO BAR'
14611      */
14612     var startCase = createCompounder(function(result, word, index) {
14613       return result + (index ? ' ' : '') + upperFirst(word);
14614     });
14615
14616     /**
14617      * Checks if `string` starts with the given target string.
14618      *
14619      * @static
14620      * @memberOf _
14621      * @since 3.0.0
14622      * @category String
14623      * @param {string} [string=''] The string to inspect.
14624      * @param {string} [target] The string to search for.
14625      * @param {number} [position=0] The position to search from.
14626      * @returns {boolean} Returns `true` if `string` starts with `target`,
14627      *  else `false`.
14628      * @example
14629      *
14630      * _.startsWith('abc', 'a');
14631      * // => true
14632      *
14633      * _.startsWith('abc', 'b');
14634      * // => false
14635      *
14636      * _.startsWith('abc', 'b', 1);
14637      * // => true
14638      */
14639     function startsWith(string, target, position) {
14640       string = toString(string);
14641       position = baseClamp(toInteger(position), 0, string.length);
14642       target = baseToString(target);
14643       return string.slice(position, position + target.length) == target;
14644     }
14645
14646     /**
14647      * Creates a compiled template function that can interpolate data properties
14648      * in "interpolate" delimiters, HTML-escape interpolated data properties in
14649      * "escape" delimiters, and execute JavaScript in "evaluate" delimiters. Data
14650      * properties may be accessed as free variables in the template. If a setting
14651      * object is given, it takes precedence over `_.templateSettings` values.
14652      *
14653      * **Note:** In the development build `_.template` utilizes
14654      * [sourceURLs](http://www.html5rocks.com/en/tutorials/developertools/sourcemaps/#toc-sourceurl)
14655      * for easier debugging.
14656      *
14657      * For more information on precompiling templates see
14658      * [lodash's custom builds documentation](https://lodash.com/custom-builds).
14659      *
14660      * For more information on Chrome extension sandboxes see
14661      * [Chrome's extensions documentation](https://developer.chrome.com/extensions/sandboxingEval).
14662      *
14663      * @static
14664      * @since 0.1.0
14665      * @memberOf _
14666      * @category String
14667      * @param {string} [string=''] The template string.
14668      * @param {Object} [options={}] The options object.
14669      * @param {RegExp} [options.escape=_.templateSettings.escape]
14670      *  The HTML "escape" delimiter.
14671      * @param {RegExp} [options.evaluate=_.templateSettings.evaluate]
14672      *  The "evaluate" delimiter.
14673      * @param {Object} [options.imports=_.templateSettings.imports]
14674      *  An object to import into the template as free variables.
14675      * @param {RegExp} [options.interpolate=_.templateSettings.interpolate]
14676      *  The "interpolate" delimiter.
14677      * @param {string} [options.sourceURL='lodash.templateSources[n]']
14678      *  The sourceURL of the compiled template.
14679      * @param {string} [options.variable='obj']
14680      *  The data object variable name.
14681      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14682      * @returns {Function} Returns the compiled template function.
14683      * @example
14684      *
14685      * // Use the "interpolate" delimiter to create a compiled template.
14686      * var compiled = _.template('hello <%= user %>!');
14687      * compiled({ 'user': 'fred' });
14688      * // => 'hello fred!'
14689      *
14690      * // Use the HTML "escape" delimiter to escape data property values.
14691      * var compiled = _.template('<b><%- value %></b>');
14692      * compiled({ 'value': '<script>' });
14693      * // => '<b>&lt;script&gt;</b>'
14694      *
14695      * // Use the "evaluate" delimiter to execute JavaScript and generate HTML.
14696      * var compiled = _.template('<% _.forEach(users, function(user) { %><li><%- user %></li><% }); %>');
14697      * compiled({ 'users': ['fred', 'barney'] });
14698      * // => '<li>fred</li><li>barney</li>'
14699      *
14700      * // Use the internal `print` function in "evaluate" delimiters.
14701      * var compiled = _.template('<% print("hello " + user); %>!');
14702      * compiled({ 'user': 'barney' });
14703      * // => 'hello barney!'
14704      *
14705      * // Use the ES template literal delimiter as an "interpolate" delimiter.
14706      * // Disable support by replacing the "interpolate" delimiter.
14707      * var compiled = _.template('hello ${ user }!');
14708      * compiled({ 'user': 'pebbles' });
14709      * // => 'hello pebbles!'
14710      *
14711      * // Use backslashes to treat delimiters as plain text.
14712      * var compiled = _.template('<%= "\\<%- value %\\>" %>');
14713      * compiled({ 'value': 'ignored' });
14714      * // => '<%- value %>'
14715      *
14716      * // Use the `imports` option to import `jQuery` as `jq`.
14717      * var text = '<% jq.each(users, function(user) { %><li><%- user %></li><% }); %>';
14718      * var compiled = _.template(text, { 'imports': { 'jq': jQuery } });
14719      * compiled({ 'users': ['fred', 'barney'] });
14720      * // => '<li>fred</li><li>barney</li>'
14721      *
14722      * // Use the `sourceURL` option to specify a custom sourceURL for the template.
14723      * var compiled = _.template('hello <%= user %>!', { 'sourceURL': '/basic/greeting.jst' });
14724      * compiled(data);
14725      * // => Find the source of "greeting.jst" under the Sources tab or Resources panel of the web inspector.
14726      *
14727      * // Use the `variable` option to ensure a with-statement isn't used in the compiled template.
14728      * var compiled = _.template('hi <%= data.user %>!', { 'variable': 'data' });
14729      * compiled.source;
14730      * // => function(data) {
14731      * //   var __t, __p = '';
14732      * //   __p += 'hi ' + ((__t = ( data.user )) == null ? '' : __t) + '!';
14733      * //   return __p;
14734      * // }
14735      *
14736      * // Use custom template delimiters.
14737      * _.templateSettings.interpolate = /{{([\s\S]+?)}}/g;
14738      * var compiled = _.template('hello {{ user }}!');
14739      * compiled({ 'user': 'mustache' });
14740      * // => 'hello mustache!'
14741      *
14742      * // Use the `source` property to inline compiled templates for meaningful
14743      * // line numbers in error messages and stack traces.
14744      * fs.writeFileSync(path.join(process.cwd(), 'jst.js'), '\
14745      *   var JST = {\
14746      *     "main": ' + _.template(mainText).source + '\
14747      *   };\
14748      * ');
14749      */
14750     function template(string, options, guard) {
14751       // Based on John Resig's `tmpl` implementation
14752       // (http://ejohn.org/blog/javascript-micro-templating/)
14753       // and Laura Doktorova's doT.js (https://github.com/olado/doT).
14754       var settings = lodash.templateSettings;
14755
14756       if (guard && isIterateeCall(string, options, guard)) {
14757         options = undefined;
14758       }
14759       string = toString(string);
14760       options = assignInWith({}, options, settings, assignInDefaults);
14761
14762       var imports = assignInWith({}, options.imports, settings.imports, assignInDefaults),
14763           importsKeys = keys(imports),
14764           importsValues = baseValues(imports, importsKeys);
14765
14766       var isEscaping,
14767           isEvaluating,
14768           index = 0,
14769           interpolate = options.interpolate || reNoMatch,
14770           source = "__p += '";
14771
14772       // Compile the regexp to match each delimiter.
14773       var reDelimiters = RegExp(
14774         (options.escape || reNoMatch).source + '|' +
14775         interpolate.source + '|' +
14776         (interpolate === reInterpolate ? reEsTemplate : reNoMatch).source + '|' +
14777         (options.evaluate || reNoMatch).source + '|$'
14778       , 'g');
14779
14780       // Use a sourceURL for easier debugging.
14781       var sourceURL = '//# sourceURL=' +
14782         ('sourceURL' in options
14783           ? options.sourceURL
14784           : ('lodash.templateSources[' + (++templateCounter) + ']')
14785         ) + '\n';
14786
14787       string.replace(reDelimiters, function(match, escapeValue, interpolateValue, esTemplateValue, evaluateValue, offset) {
14788         interpolateValue || (interpolateValue = esTemplateValue);
14789
14790         // Escape characters that can't be included in string literals.
14791         source += string.slice(index, offset).replace(reUnescapedString, escapeStringChar);
14792
14793         // Replace delimiters with snippets.
14794         if (escapeValue) {
14795           isEscaping = true;
14796           source += "' +\n__e(" + escapeValue + ") +\n'";
14797         }
14798         if (evaluateValue) {
14799           isEvaluating = true;
14800           source += "';\n" + evaluateValue + ";\n__p += '";
14801         }
14802         if (interpolateValue) {
14803           source += "' +\n((__t = (" + interpolateValue + ")) == null ? '' : __t) +\n'";
14804         }
14805         index = offset + match.length;
14806
14807         // The JS engine embedded in Adobe products needs `match` returned in
14808         // order to produce the correct `offset` value.
14809         return match;
14810       });
14811
14812       source += "';\n";
14813
14814       // If `variable` is not specified wrap a with-statement around the generated
14815       // code to add the data object to the top of the scope chain.
14816       var variable = options.variable;
14817       if (!variable) {
14818         source = 'with (obj) {\n' + source + '\n}\n';
14819       }
14820       // Cleanup code by stripping empty strings.
14821       source = (isEvaluating ? source.replace(reEmptyStringLeading, '') : source)
14822         .replace(reEmptyStringMiddle, '$1')
14823         .replace(reEmptyStringTrailing, '$1;');
14824
14825       // Frame code as the function body.
14826       source = 'function(' + (variable || 'obj') + ') {\n' +
14827         (variable
14828           ? ''
14829           : 'obj || (obj = {});\n'
14830         ) +
14831         "var __t, __p = ''" +
14832         (isEscaping
14833            ? ', __e = _.escape'
14834            : ''
14835         ) +
14836         (isEvaluating
14837           ? ', __j = Array.prototype.join;\n' +
14838             "function print() { __p += __j.call(arguments, '') }\n"
14839           : ';\n'
14840         ) +
14841         source +
14842         'return __p\n}';
14843
14844       var result = attempt(function() {
14845         return Function(importsKeys, sourceURL + 'return ' + source)
14846           .apply(undefined, importsValues);
14847       });
14848
14849       // Provide the compiled function's source by its `toString` method or
14850       // the `source` property as a convenience for inlining compiled templates.
14851       result.source = source;
14852       if (isError(result)) {
14853         throw result;
14854       }
14855       return result;
14856     }
14857
14858     /**
14859      * Converts `string`, as a whole, to lower case just like
14860      * [String#toLowerCase](https://mdn.io/toLowerCase).
14861      *
14862      * @static
14863      * @memberOf _
14864      * @since 4.0.0
14865      * @category String
14866      * @param {string} [string=''] The string to convert.
14867      * @returns {string} Returns the lower cased string.
14868      * @example
14869      *
14870      * _.toLower('--Foo-Bar--');
14871      * // => '--foo-bar--'
14872      *
14873      * _.toLower('fooBar');
14874      * // => 'foobar'
14875      *
14876      * _.toLower('__FOO_BAR__');
14877      * // => '__foo_bar__'
14878      */
14879     function toLower(value) {
14880       return toString(value).toLowerCase();
14881     }
14882
14883     /**
14884      * Converts `string`, as a whole, to upper case just like
14885      * [String#toUpperCase](https://mdn.io/toUpperCase).
14886      *
14887      * @static
14888      * @memberOf _
14889      * @since 4.0.0
14890      * @category String
14891      * @param {string} [string=''] The string to convert.
14892      * @returns {string} Returns the upper cased string.
14893      * @example
14894      *
14895      * _.toUpper('--foo-bar--');
14896      * // => '--FOO-BAR--'
14897      *
14898      * _.toUpper('fooBar');
14899      * // => 'FOOBAR'
14900      *
14901      * _.toUpper('__foo_bar__');
14902      * // => '__FOO_BAR__'
14903      */
14904     function toUpper(value) {
14905       return toString(value).toUpperCase();
14906     }
14907
14908     /**
14909      * Removes leading and trailing whitespace or specified characters from `string`.
14910      *
14911      * @static
14912      * @memberOf _
14913      * @since 3.0.0
14914      * @category String
14915      * @param {string} [string=''] The string to trim.
14916      * @param {string} [chars=whitespace] The characters to trim.
14917      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14918      * @returns {string} Returns the trimmed string.
14919      * @example
14920      *
14921      * _.trim('  abc  ');
14922      * // => 'abc'
14923      *
14924      * _.trim('-_-abc-_-', '_-');
14925      * // => 'abc'
14926      *
14927      * _.map(['  foo  ', '  bar  '], _.trim);
14928      * // => ['foo', 'bar']
14929      */
14930     function trim(string, chars, guard) {
14931       string = toString(string);
14932       if (string && (guard || chars === undefined)) {
14933         return string.replace(reTrim, '');
14934       }
14935       if (!string || !(chars = baseToString(chars))) {
14936         return string;
14937       }
14938       var strSymbols = stringToArray(string),
14939           chrSymbols = stringToArray(chars),
14940           start = charsStartIndex(strSymbols, chrSymbols),
14941           end = charsEndIndex(strSymbols, chrSymbols) + 1;
14942
14943       return castSlice(strSymbols, start, end).join('');
14944     }
14945
14946     /**
14947      * Removes trailing whitespace or specified characters from `string`.
14948      *
14949      * @static
14950      * @memberOf _
14951      * @since 4.0.0
14952      * @category String
14953      * @param {string} [string=''] The string to trim.
14954      * @param {string} [chars=whitespace] The characters to trim.
14955      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14956      * @returns {string} Returns the trimmed string.
14957      * @example
14958      *
14959      * _.trimEnd('  abc  ');
14960      * // => '  abc'
14961      *
14962      * _.trimEnd('-_-abc-_-', '_-');
14963      * // => '-_-abc'
14964      */
14965     function trimEnd(string, chars, guard) {
14966       string = toString(string);
14967       if (string && (guard || chars === undefined)) {
14968         return string.replace(reTrimEnd, '');
14969       }
14970       if (!string || !(chars = baseToString(chars))) {
14971         return string;
14972       }
14973       var strSymbols = stringToArray(string),
14974           end = charsEndIndex(strSymbols, stringToArray(chars)) + 1;
14975
14976       return castSlice(strSymbols, 0, end).join('');
14977     }
14978
14979     /**
14980      * Removes leading whitespace or specified characters from `string`.
14981      *
14982      * @static
14983      * @memberOf _
14984      * @since 4.0.0
14985      * @category String
14986      * @param {string} [string=''] The string to trim.
14987      * @param {string} [chars=whitespace] The characters to trim.
14988      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
14989      * @returns {string} Returns the trimmed string.
14990      * @example
14991      *
14992      * _.trimStart('  abc  ');
14993      * // => 'abc  '
14994      *
14995      * _.trimStart('-_-abc-_-', '_-');
14996      * // => 'abc-_-'
14997      */
14998     function trimStart(string, chars, guard) {
14999       string = toString(string);
15000       if (string && (guard || chars === undefined)) {
15001         return string.replace(reTrimStart, '');
15002       }
15003       if (!string || !(chars = baseToString(chars))) {
15004         return string;
15005       }
15006       var strSymbols = stringToArray(string),
15007           start = charsStartIndex(strSymbols, stringToArray(chars));
15008
15009       return castSlice(strSymbols, start).join('');
15010     }
15011
15012     /**
15013      * Truncates `string` if it's longer than the given maximum string length.
15014      * The last characters of the truncated string are replaced with the omission
15015      * string which defaults to "...".
15016      *
15017      * @static
15018      * @memberOf _
15019      * @since 4.0.0
15020      * @category String
15021      * @param {string} [string=''] The string to truncate.
15022      * @param {Object} [options={}] The options object.
15023      * @param {number} [options.length=30] The maximum string length.
15024      * @param {string} [options.omission='...'] The string to indicate text is omitted.
15025      * @param {RegExp|string} [options.separator] The separator pattern to truncate to.
15026      * @returns {string} Returns the truncated string.
15027      * @example
15028      *
15029      * _.truncate('hi-diddly-ho there, neighborino');
15030      * // => 'hi-diddly-ho there, neighbo...'
15031      *
15032      * _.truncate('hi-diddly-ho there, neighborino', {
15033      *   'length': 24,
15034      *   'separator': ' '
15035      * });
15036      * // => 'hi-diddly-ho there,...'
15037      *
15038      * _.truncate('hi-diddly-ho there, neighborino', {
15039      *   'length': 24,
15040      *   'separator': /,? +/
15041      * });
15042      * // => 'hi-diddly-ho there...'
15043      *
15044      * _.truncate('hi-diddly-ho there, neighborino', {
15045      *   'omission': ' [...]'
15046      * });
15047      * // => 'hi-diddly-ho there, neig [...]'
15048      */
15049     function truncate(string, options) {
15050       var length = DEFAULT_TRUNC_LENGTH,
15051           omission = DEFAULT_TRUNC_OMISSION;
15052
15053       if (isObject(options)) {
15054         var separator = 'separator' in options ? options.separator : separator;
15055         length = 'length' in options ? toInteger(options.length) : length;
15056         omission = 'omission' in options ? baseToString(options.omission) : omission;
15057       }
15058       string = toString(string);
15059
15060       var strLength = string.length;
15061       if (hasUnicode(string)) {
15062         var strSymbols = stringToArray(string);
15063         strLength = strSymbols.length;
15064       }
15065       if (length >= strLength) {
15066         return string;
15067       }
15068       var end = length - stringSize(omission);
15069       if (end < 1) {
15070         return omission;
15071       }
15072       var result = strSymbols
15073         ? castSlice(strSymbols, 0, end).join('')
15074         : string.slice(0, end);
15075
15076       if (separator === undefined) {
15077         return result + omission;
15078       }
15079       if (strSymbols) {
15080         end += (result.length - end);
15081       }
15082       if (isRegExp(separator)) {
15083         if (string.slice(end).search(separator)) {
15084           var match,
15085               substring = result;
15086
15087           if (!separator.global) {
15088             separator = RegExp(separator.source, toString(reFlags.exec(separator)) + 'g');
15089           }
15090           separator.lastIndex = 0;
15091           while ((match = separator.exec(substring))) {
15092             var newEnd = match.index;
15093           }
15094           result = result.slice(0, newEnd === undefined ? end : newEnd);
15095         }
15096       } else if (string.indexOf(baseToString(separator), end) != end) {
15097         var index = result.lastIndexOf(separator);
15098         if (index > -1) {
15099           result = result.slice(0, index);
15100         }
15101       }
15102       return result + omission;
15103     }
15104
15105     /**
15106      * The inverse of `_.escape`; this method converts the HTML entities
15107      * `&amp;`, `&lt;`, `&gt;`, `&quot;`, and `&#39;` in `string` to
15108      * their corresponding characters.
15109      *
15110      * **Note:** No other HTML entities are unescaped. To unescape additional
15111      * HTML entities use a third-party library like [_he_](https://mths.be/he).
15112      *
15113      * @static
15114      * @memberOf _
15115      * @since 0.6.0
15116      * @category String
15117      * @param {string} [string=''] The string to unescape.
15118      * @returns {string} Returns the unescaped string.
15119      * @example
15120      *
15121      * _.unescape('fred, barney, &amp; pebbles');
15122      * // => 'fred, barney, & pebbles'
15123      */
15124     function unescape(string) {
15125       string = toString(string);
15126       return (string && reHasEscapedHtml.test(string))
15127         ? string.replace(reEscapedHtml, unescapeHtmlChar)
15128         : string;
15129     }
15130
15131     /**
15132      * Converts `string`, as space separated words, to upper case.
15133      *
15134      * @static
15135      * @memberOf _
15136      * @since 4.0.0
15137      * @category String
15138      * @param {string} [string=''] The string to convert.
15139      * @returns {string} Returns the upper cased string.
15140      * @example
15141      *
15142      * _.upperCase('--foo-bar');
15143      * // => 'FOO BAR'
15144      *
15145      * _.upperCase('fooBar');
15146      * // => 'FOO BAR'
15147      *
15148      * _.upperCase('__foo_bar__');
15149      * // => 'FOO BAR'
15150      */
15151     var upperCase = createCompounder(function(result, word, index) {
15152       return result + (index ? ' ' : '') + word.toUpperCase();
15153     });
15154
15155     /**
15156      * Converts the first character of `string` to upper case.
15157      *
15158      * @static
15159      * @memberOf _
15160      * @since 4.0.0
15161      * @category String
15162      * @param {string} [string=''] The string to convert.
15163      * @returns {string} Returns the converted string.
15164      * @example
15165      *
15166      * _.upperFirst('fred');
15167      * // => 'Fred'
15168      *
15169      * _.upperFirst('FRED');
15170      * // => 'FRED'
15171      */
15172     var upperFirst = createCaseFirst('toUpperCase');
15173
15174     /**
15175      * Splits `string` into an array of its words.
15176      *
15177      * @static
15178      * @memberOf _
15179      * @since 3.0.0
15180      * @category String
15181      * @param {string} [string=''] The string to inspect.
15182      * @param {RegExp|string} [pattern] The pattern to match words.
15183      * @param- {Object} [guard] Enables use as an iteratee for methods like `_.map`.
15184      * @returns {Array} Returns the words of `string`.
15185      * @example
15186      *
15187      * _.words('fred, barney, & pebbles');
15188      * // => ['fred', 'barney', 'pebbles']
15189      *
15190      * _.words('fred, barney, & pebbles', /[^, ]+/g);
15191      * // => ['fred', 'barney', '&', 'pebbles']
15192      */
15193     function words(string, pattern, guard) {
15194       string = toString(string);
15195       pattern = guard ? undefined : pattern;
15196
15197       if (pattern === undefined) {
15198         return hasUnicodeWord(string) ? unicodeWords(string) : asciiWords(string);
15199       }
15200       return string.match(pattern) || [];
15201     }
15202
15203     /*------------------------------------------------------------------------*/
15204
15205     /**
15206      * Attempts to invoke `func`, returning either the result or the caught error
15207      * object. Any additional arguments are provided to `func` when it's invoked.
15208      *
15209      * @static
15210      * @memberOf _
15211      * @since 3.0.0
15212      * @category Util
15213      * @param {Function} func The function to attempt.
15214      * @param {...*} [args] The arguments to invoke `func` with.
15215      * @returns {*} Returns the `func` result or error object.
15216      * @example
15217      *
15218      * // Avoid throwing errors for invalid selectors.
15219      * var elements = _.attempt(function(selector) {
15220      *   return document.querySelectorAll(selector);
15221      * }, '>_>');
15222      *
15223      * if (_.isError(elements)) {
15224      *   elements = [];
15225      * }
15226      */
15227     var attempt = baseRest(function(func, args) {
15228       try {
15229         return apply(func, undefined, args);
15230       } catch (e) {
15231         return isError(e) ? e : new Error(e);
15232       }
15233     });
15234
15235     /**
15236      * Binds methods of an object to the object itself, overwriting the existing
15237      * method.
15238      *
15239      * **Note:** This method doesn't set the "length" property of bound functions.
15240      *
15241      * @static
15242      * @since 0.1.0
15243      * @memberOf _
15244      * @category Util
15245      * @param {Object} object The object to bind and assign the bound methods to.
15246      * @param {...(string|string[])} methodNames The object method names to bind.
15247      * @returns {Object} Returns `object`.
15248      * @example
15249      *
15250      * var view = {
15251      *   'label': 'docs',
15252      *   'click': function() {
15253      *     console.log('clicked ' + this.label);
15254      *   }
15255      * };
15256      *
15257      * _.bindAll(view, ['click']);
15258      * jQuery(element).on('click', view.click);
15259      * // => Logs 'clicked docs' when clicked.
15260      */
15261     var bindAll = flatRest(function(object, methodNames) {
15262       arrayEach(methodNames, function(key) {
15263         key = toKey(key);
15264         baseAssignValue(object, key, bind(object[key], object));
15265       });
15266       return object;
15267     });
15268
15269     /**
15270      * Creates a function that iterates over `pairs` and invokes the corresponding
15271      * function of the first predicate to return truthy. The predicate-function
15272      * pairs are invoked with the `this` binding and arguments of the created
15273      * function.
15274      *
15275      * @static
15276      * @memberOf _
15277      * @since 4.0.0
15278      * @category Util
15279      * @param {Array} pairs The predicate-function pairs.
15280      * @returns {Function} Returns the new composite function.
15281      * @example
15282      *
15283      * var func = _.cond([
15284      *   [_.matches({ 'a': 1 }),           _.constant('matches A')],
15285      *   [_.conforms({ 'b': _.isNumber }), _.constant('matches B')],
15286      *   [_.stubTrue,                      _.constant('no match')]
15287      * ]);
15288      *
15289      * func({ 'a': 1, 'b': 2 });
15290      * // => 'matches A'
15291      *
15292      * func({ 'a': 0, 'b': 1 });
15293      * // => 'matches B'
15294      *
15295      * func({ 'a': '1', 'b': '2' });
15296      * // => 'no match'
15297      */
15298     function cond(pairs) {
15299       var length = pairs == null ? 0 : pairs.length,
15300           toIteratee = getIteratee();
15301
15302       pairs = !length ? [] : arrayMap(pairs, function(pair) {
15303         if (typeof pair[1] != 'function') {
15304           throw new TypeError(FUNC_ERROR_TEXT);
15305         }
15306         return [toIteratee(pair[0]), pair[1]];
15307       });
15308
15309       return baseRest(function(args) {
15310         var index = -1;
15311         while (++index < length) {
15312           var pair = pairs[index];
15313           if (apply(pair[0], this, args)) {
15314             return apply(pair[1], this, args);
15315           }
15316         }
15317       });
15318     }
15319
15320     /**
15321      * Creates a function that invokes the predicate properties of `source` with
15322      * the corresponding property values of a given object, returning `true` if
15323      * all predicates return truthy, else `false`.
15324      *
15325      * **Note:** The created function is equivalent to `_.conformsTo` with
15326      * `source` partially applied.
15327      *
15328      * @static
15329      * @memberOf _
15330      * @since 4.0.0
15331      * @category Util
15332      * @param {Object} source The object of property predicates to conform to.
15333      * @returns {Function} Returns the new spec function.
15334      * @example
15335      *
15336      * var objects = [
15337      *   { 'a': 2, 'b': 1 },
15338      *   { 'a': 1, 'b': 2 }
15339      * ];
15340      *
15341      * _.filter(objects, _.conforms({ 'b': function(n) { return n > 1; } }));
15342      * // => [{ 'a': 1, 'b': 2 }]
15343      */
15344     function conforms(source) {
15345       return baseConforms(baseClone(source, CLONE_DEEP_FLAG));
15346     }
15347
15348     /**
15349      * Creates a function that returns `value`.
15350      *
15351      * @static
15352      * @memberOf _
15353      * @since 2.4.0
15354      * @category Util
15355      * @param {*} value The value to return from the new function.
15356      * @returns {Function} Returns the new constant function.
15357      * @example
15358      *
15359      * var objects = _.times(2, _.constant({ 'a': 1 }));
15360      *
15361      * console.log(objects);
15362      * // => [{ 'a': 1 }, { 'a': 1 }]
15363      *
15364      * console.log(objects[0] === objects[1]);
15365      * // => true
15366      */
15367     function constant(value) {
15368       return function() {
15369         return value;
15370       };
15371     }
15372
15373     /**
15374      * Checks `value` to determine whether a default value should be returned in
15375      * its place. The `defaultValue` is returned if `value` is `NaN`, `null`,
15376      * or `undefined`.
15377      *
15378      * @static
15379      * @memberOf _
15380      * @since 4.14.0
15381      * @category Util
15382      * @param {*} value The value to check.
15383      * @param {*} defaultValue The default value.
15384      * @returns {*} Returns the resolved value.
15385      * @example
15386      *
15387      * _.defaultTo(1, 10);
15388      * // => 1
15389      *
15390      * _.defaultTo(undefined, 10);
15391      * // => 10
15392      */
15393     function defaultTo(value, defaultValue) {
15394       return (value == null || value !== value) ? defaultValue : value;
15395     }
15396
15397     /**
15398      * Creates a function that returns the result of invoking the given functions
15399      * with the `this` binding of the created function, where each successive
15400      * invocation is supplied the return value of the previous.
15401      *
15402      * @static
15403      * @memberOf _
15404      * @since 3.0.0
15405      * @category Util
15406      * @param {...(Function|Function[])} [funcs] The functions to invoke.
15407      * @returns {Function} Returns the new composite function.
15408      * @see _.flowRight
15409      * @example
15410      *
15411      * function square(n) {
15412      *   return n * n;
15413      * }
15414      *
15415      * var addSquare = _.flow([_.add, square]);
15416      * addSquare(1, 2);
15417      * // => 9
15418      */
15419     var flow = createFlow();
15420
15421     /**
15422      * This method is like `_.flow` except that it creates a function that
15423      * invokes the given functions from right to left.
15424      *
15425      * @static
15426      * @since 3.0.0
15427      * @memberOf _
15428      * @category Util
15429      * @param {...(Function|Function[])} [funcs] The functions to invoke.
15430      * @returns {Function} Returns the new composite function.
15431      * @see _.flow
15432      * @example
15433      *
15434      * function square(n) {
15435      *   return n * n;
15436      * }
15437      *
15438      * var addSquare = _.flowRight([square, _.add]);
15439      * addSquare(1, 2);
15440      * // => 9
15441      */
15442     var flowRight = createFlow(true);
15443
15444     /**
15445      * This method returns the first argument it receives.
15446      *
15447      * @static
15448      * @since 0.1.0
15449      * @memberOf _
15450      * @category Util
15451      * @param {*} value Any value.
15452      * @returns {*} Returns `value`.
15453      * @example
15454      *
15455      * var object = { 'a': 1 };
15456      *
15457      * console.log(_.identity(object) === object);
15458      * // => true
15459      */
15460     function identity(value) {
15461       return value;
15462     }
15463
15464     /**
15465      * Creates a function that invokes `func` with the arguments of the created
15466      * function. If `func` is a property name, the created function returns the
15467      * property value for a given element. If `func` is an array or object, the
15468      * created function returns `true` for elements that contain the equivalent
15469      * source properties, otherwise it returns `false`.
15470      *
15471      * @static
15472      * @since 4.0.0
15473      * @memberOf _
15474      * @category Util
15475      * @param {*} [func=_.identity] The value to convert to a callback.
15476      * @returns {Function} Returns the callback.
15477      * @example
15478      *
15479      * var users = [
15480      *   { 'user': 'barney', 'age': 36, 'active': true },
15481      *   { 'user': 'fred',   'age': 40, 'active': false }
15482      * ];
15483      *
15484      * // The `_.matches` iteratee shorthand.
15485      * _.filter(users, _.iteratee({ 'user': 'barney', 'active': true }));
15486      * // => [{ 'user': 'barney', 'age': 36, 'active': true }]
15487      *
15488      * // The `_.matchesProperty` iteratee shorthand.
15489      * _.filter(users, _.iteratee(['user', 'fred']));
15490      * // => [{ 'user': 'fred', 'age': 40 }]
15491      *
15492      * // The `_.property` iteratee shorthand.
15493      * _.map(users, _.iteratee('user'));
15494      * // => ['barney', 'fred']
15495      *
15496      * // Create custom iteratee shorthands.
15497      * _.iteratee = _.wrap(_.iteratee, function(iteratee, func) {
15498      *   return !_.isRegExp(func) ? iteratee(func) : function(string) {
15499      *     return func.test(string);
15500      *   };
15501      * });
15502      *
15503      * _.filter(['abc', 'def'], /ef/);
15504      * // => ['def']
15505      */
15506     function iteratee(func) {
15507       return baseIteratee(typeof func == 'function' ? func : baseClone(func, CLONE_DEEP_FLAG));
15508     }
15509
15510     /**
15511      * Creates a function that performs a partial deep comparison between a given
15512      * object and `source`, returning `true` if the given object has equivalent
15513      * property values, else `false`.
15514      *
15515      * **Note:** The created function is equivalent to `_.isMatch` with `source`
15516      * partially applied.
15517      *
15518      * Partial comparisons will match empty array and empty object `source`
15519      * values against any array or object value, respectively. See `_.isEqual`
15520      * for a list of supported value comparisons.
15521      *
15522      * @static
15523      * @memberOf _
15524      * @since 3.0.0
15525      * @category Util
15526      * @param {Object} source The object of property values to match.
15527      * @returns {Function} Returns the new spec function.
15528      * @example
15529      *
15530      * var objects = [
15531      *   { 'a': 1, 'b': 2, 'c': 3 },
15532      *   { 'a': 4, 'b': 5, 'c': 6 }
15533      * ];
15534      *
15535      * _.filter(objects, _.matches({ 'a': 4, 'c': 6 }));
15536      * // => [{ 'a': 4, 'b': 5, 'c': 6 }]
15537      */
15538     function matches(source) {
15539       return baseMatches(baseClone(source, CLONE_DEEP_FLAG));
15540     }
15541
15542     /**
15543      * Creates a function that performs a partial deep comparison between the
15544      * value at `path` of a given object to `srcValue`, returning `true` if the
15545      * object value is equivalent, else `false`.
15546      *
15547      * **Note:** Partial comparisons will match empty array and empty object
15548      * `srcValue` values against any array or object value, respectively. See
15549      * `_.isEqual` for a list of supported value comparisons.
15550      *
15551      * @static
15552      * @memberOf _
15553      * @since 3.2.0
15554      * @category Util
15555      * @param {Array|string} path The path of the property to get.
15556      * @param {*} srcValue The value to match.
15557      * @returns {Function} Returns the new spec function.
15558      * @example
15559      *
15560      * var objects = [
15561      *   { 'a': 1, 'b': 2, 'c': 3 },
15562      *   { 'a': 4, 'b': 5, 'c': 6 }
15563      * ];
15564      *
15565      * _.find(objects, _.matchesProperty('a', 4));
15566      * // => { 'a': 4, 'b': 5, 'c': 6 }
15567      */
15568     function matchesProperty(path, srcValue) {
15569       return baseMatchesProperty(path, baseClone(srcValue, CLONE_DEEP_FLAG));
15570     }
15571
15572     /**
15573      * Creates a function that invokes the method at `path` of a given object.
15574      * Any additional arguments are provided to the invoked method.
15575      *
15576      * @static
15577      * @memberOf _
15578      * @since 3.7.0
15579      * @category Util
15580      * @param {Array|string} path The path of the method to invoke.
15581      * @param {...*} [args] The arguments to invoke the method with.
15582      * @returns {Function} Returns the new invoker function.
15583      * @example
15584      *
15585      * var objects = [
15586      *   { 'a': { 'b': _.constant(2) } },
15587      *   { 'a': { 'b': _.constant(1) } }
15588      * ];
15589      *
15590      * _.map(objects, _.method('a.b'));
15591      * // => [2, 1]
15592      *
15593      * _.map(objects, _.method(['a', 'b']));
15594      * // => [2, 1]
15595      */
15596     var method = baseRest(function(path, args) {
15597       return function(object) {
15598         return baseInvoke(object, path, args);
15599       };
15600     });
15601
15602     /**
15603      * The opposite of `_.method`; this method creates a function that invokes
15604      * the method at a given path of `object`. Any additional arguments are
15605      * provided to the invoked method.
15606      *
15607      * @static
15608      * @memberOf _
15609      * @since 3.7.0
15610      * @category Util
15611      * @param {Object} object The object to query.
15612      * @param {...*} [args] The arguments to invoke the method with.
15613      * @returns {Function} Returns the new invoker function.
15614      * @example
15615      *
15616      * var array = _.times(3, _.constant),
15617      *     object = { 'a': array, 'b': array, 'c': array };
15618      *
15619      * _.map(['a[2]', 'c[0]'], _.methodOf(object));
15620      * // => [2, 0]
15621      *
15622      * _.map([['a', '2'], ['c', '0']], _.methodOf(object));
15623      * // => [2, 0]
15624      */
15625     var methodOf = baseRest(function(object, args) {
15626       return function(path) {
15627         return baseInvoke(object, path, args);
15628       };
15629     });
15630
15631     /**
15632      * Adds all own enumerable string keyed function properties of a source
15633      * object to the destination object. If `object` is a function, then methods
15634      * are added to its prototype as well.
15635      *
15636      * **Note:** Use `_.runInContext` to create a pristine `lodash` function to
15637      * avoid conflicts caused by modifying the original.
15638      *
15639      * @static
15640      * @since 0.1.0
15641      * @memberOf _
15642      * @category Util
15643      * @param {Function|Object} [object=lodash] The destination object.
15644      * @param {Object} source The object of functions to add.
15645      * @param {Object} [options={}] The options object.
15646      * @param {boolean} [options.chain=true] Specify whether mixins are chainable.
15647      * @returns {Function|Object} Returns `object`.
15648      * @example
15649      *
15650      * function vowels(string) {
15651      *   return _.filter(string, function(v) {
15652      *     return /[aeiou]/i.test(v);
15653      *   });
15654      * }
15655      *
15656      * _.mixin({ 'vowels': vowels });
15657      * _.vowels('fred');
15658      * // => ['e']
15659      *
15660      * _('fred').vowels().value();
15661      * // => ['e']
15662      *
15663      * _.mixin({ 'vowels': vowels }, { 'chain': false });
15664      * _('fred').vowels();
15665      * // => ['e']
15666      */
15667     function mixin(object, source, options) {
15668       var props = keys(source),
15669           methodNames = baseFunctions(source, props);
15670
15671       if (options == null &&
15672           !(isObject(source) && (methodNames.length || !props.length))) {
15673         options = source;
15674         source = object;
15675         object = this;
15676         methodNames = baseFunctions(source, keys(source));
15677       }
15678       var chain = !(isObject(options) && 'chain' in options) || !!options.chain,
15679           isFunc = isFunction(object);
15680
15681       arrayEach(methodNames, function(methodName) {
15682         var func = source[methodName];
15683         object[methodName] = func;
15684         if (isFunc) {
15685           object.prototype[methodName] = function() {
15686             var chainAll = this.__chain__;
15687             if (chain || chainAll) {
15688               var result = object(this.__wrapped__),
15689                   actions = result.__actions__ = copyArray(this.__actions__);
15690
15691               actions.push({ 'func': func, 'args': arguments, 'thisArg': object });
15692               result.__chain__ = chainAll;
15693               return result;
15694             }
15695             return func.apply(object, arrayPush([this.value()], arguments));
15696           };
15697         }
15698       });
15699
15700       return object;
15701     }
15702
15703     /**
15704      * Reverts the `_` variable to its previous value and returns a reference to
15705      * the `lodash` function.
15706      *
15707      * @static
15708      * @since 0.1.0
15709      * @memberOf _
15710      * @category Util
15711      * @returns {Function} Returns the `lodash` function.
15712      * @example
15713      *
15714      * var lodash = _.noConflict();
15715      */
15716     function noConflict() {
15717       if (root._ === this) {
15718         root._ = oldDash;
15719       }
15720       return this;
15721     }
15722
15723     /**
15724      * This method returns `undefined`.
15725      *
15726      * @static
15727      * @memberOf _
15728      * @since 2.3.0
15729      * @category Util
15730      * @example
15731      *
15732      * _.times(2, _.noop);
15733      * // => [undefined, undefined]
15734      */
15735     function noop() {
15736       // No operation performed.
15737     }
15738
15739     /**
15740      * Creates a function that gets the argument at index `n`. If `n` is negative,
15741      * the nth argument from the end is returned.
15742      *
15743      * @static
15744      * @memberOf _
15745      * @since 4.0.0
15746      * @category Util
15747      * @param {number} [n=0] The index of the argument to return.
15748      * @returns {Function} Returns the new pass-thru function.
15749      * @example
15750      *
15751      * var func = _.nthArg(1);
15752      * func('a', 'b', 'c', 'd');
15753      * // => 'b'
15754      *
15755      * var func = _.nthArg(-2);
15756      * func('a', 'b', 'c', 'd');
15757      * // => 'c'
15758      */
15759     function nthArg(n) {
15760       n = toInteger(n);
15761       return baseRest(function(args) {
15762         return baseNth(args, n);
15763       });
15764     }
15765
15766     /**
15767      * Creates a function that invokes `iteratees` with the arguments it receives
15768      * and returns their results.
15769      *
15770      * @static
15771      * @memberOf _
15772      * @since 4.0.0
15773      * @category Util
15774      * @param {...(Function|Function[])} [iteratees=[_.identity]]
15775      *  The iteratees to invoke.
15776      * @returns {Function} Returns the new function.
15777      * @example
15778      *
15779      * var func = _.over([Math.max, Math.min]);
15780      *
15781      * func(1, 2, 3, 4);
15782      * // => [4, 1]
15783      */
15784     var over = createOver(arrayMap);
15785
15786     /**
15787      * Creates a function that checks if **all** of the `predicates` return
15788      * truthy when invoked with the arguments it receives.
15789      *
15790      * @static
15791      * @memberOf _
15792      * @since 4.0.0
15793      * @category Util
15794      * @param {...(Function|Function[])} [predicates=[_.identity]]
15795      *  The predicates to check.
15796      * @returns {Function} Returns the new function.
15797      * @example
15798      *
15799      * var func = _.overEvery([Boolean, isFinite]);
15800      *
15801      * func('1');
15802      * // => true
15803      *
15804      * func(null);
15805      * // => false
15806      *
15807      * func(NaN);
15808      * // => false
15809      */
15810     var overEvery = createOver(arrayEvery);
15811
15812     /**
15813      * Creates a function that checks if **any** of the `predicates` return
15814      * truthy when invoked with the arguments it receives.
15815      *
15816      * @static
15817      * @memberOf _
15818      * @since 4.0.0
15819      * @category Util
15820      * @param {...(Function|Function[])} [predicates=[_.identity]]
15821      *  The predicates to check.
15822      * @returns {Function} Returns the new function.
15823      * @example
15824      *
15825      * var func = _.overSome([Boolean, isFinite]);
15826      *
15827      * func('1');
15828      * // => true
15829      *
15830      * func(null);
15831      * // => true
15832      *
15833      * func(NaN);
15834      * // => false
15835      */
15836     var overSome = createOver(arraySome);
15837
15838     /**
15839      * Creates a function that returns the value at `path` of a given object.
15840      *
15841      * @static
15842      * @memberOf _
15843      * @since 2.4.0
15844      * @category Util
15845      * @param {Array|string} path The path of the property to get.
15846      * @returns {Function} Returns the new accessor function.
15847      * @example
15848      *
15849      * var objects = [
15850      *   { 'a': { 'b': 2 } },
15851      *   { 'a': { 'b': 1 } }
15852      * ];
15853      *
15854      * _.map(objects, _.property('a.b'));
15855      * // => [2, 1]
15856      *
15857      * _.map(_.sortBy(objects, _.property(['a', 'b'])), 'a.b');
15858      * // => [1, 2]
15859      */
15860     function property(path) {
15861       return isKey(path) ? baseProperty(toKey(path)) : basePropertyDeep(path);
15862     }
15863
15864     /**
15865      * The opposite of `_.property`; this method creates a function that returns
15866      * the value at a given path of `object`.
15867      *
15868      * @static
15869      * @memberOf _
15870      * @since 3.0.0
15871      * @category Util
15872      * @param {Object} object The object to query.
15873      * @returns {Function} Returns the new accessor function.
15874      * @example
15875      *
15876      * var array = [0, 1, 2],
15877      *     object = { 'a': array, 'b': array, 'c': array };
15878      *
15879      * _.map(['a[2]', 'c[0]'], _.propertyOf(object));
15880      * // => [2, 0]
15881      *
15882      * _.map([['a', '2'], ['c', '0']], _.propertyOf(object));
15883      * // => [2, 0]
15884      */
15885     function propertyOf(object) {
15886       return function(path) {
15887         return object == null ? undefined : baseGet(object, path);
15888       };
15889     }
15890
15891     /**
15892      * Creates an array of numbers (positive and/or negative) progressing from
15893      * `start` up to, but not including, `end`. A step of `-1` is used if a negative
15894      * `start` is specified without an `end` or `step`. If `end` is not specified,
15895      * it's set to `start` with `start` then set to `0`.
15896      *
15897      * **Note:** JavaScript follows the IEEE-754 standard for resolving
15898      * floating-point values which can produce unexpected results.
15899      *
15900      * @static
15901      * @since 0.1.0
15902      * @memberOf _
15903      * @category Util
15904      * @param {number} [start=0] The start of the range.
15905      * @param {number} end The end of the range.
15906      * @param {number} [step=1] The value to increment or decrement by.
15907      * @returns {Array} Returns the range of numbers.
15908      * @see _.inRange, _.rangeRight
15909      * @example
15910      *
15911      * _.range(4);
15912      * // => [0, 1, 2, 3]
15913      *
15914      * _.range(-4);
15915      * // => [0, -1, -2, -3]
15916      *
15917      * _.range(1, 5);
15918      * // => [1, 2, 3, 4]
15919      *
15920      * _.range(0, 20, 5);
15921      * // => [0, 5, 10, 15]
15922      *
15923      * _.range(0, -4, -1);
15924      * // => [0, -1, -2, -3]
15925      *
15926      * _.range(1, 4, 0);
15927      * // => [1, 1, 1]
15928      *
15929      * _.range(0);
15930      * // => []
15931      */
15932     var range = createRange();
15933
15934     /**
15935      * This method is like `_.range` except that it populates values in
15936      * descending order.
15937      *
15938      * @static
15939      * @memberOf _
15940      * @since 4.0.0
15941      * @category Util
15942      * @param {number} [start=0] The start of the range.
15943      * @param {number} end The end of the range.
15944      * @param {number} [step=1] The value to increment or decrement by.
15945      * @returns {Array} Returns the range of numbers.
15946      * @see _.inRange, _.range
15947      * @example
15948      *
15949      * _.rangeRight(4);
15950      * // => [3, 2, 1, 0]
15951      *
15952      * _.rangeRight(-4);
15953      * // => [-3, -2, -1, 0]
15954      *
15955      * _.rangeRight(1, 5);
15956      * // => [4, 3, 2, 1]
15957      *
15958      * _.rangeRight(0, 20, 5);
15959      * // => [15, 10, 5, 0]
15960      *
15961      * _.rangeRight(0, -4, -1);
15962      * // => [-3, -2, -1, 0]
15963      *
15964      * _.rangeRight(1, 4, 0);
15965      * // => [1, 1, 1]
15966      *
15967      * _.rangeRight(0);
15968      * // => []
15969      */
15970     var rangeRight = createRange(true);
15971
15972     /**
15973      * This method returns a new empty array.
15974      *
15975      * @static
15976      * @memberOf _
15977      * @since 4.13.0
15978      * @category Util
15979      * @returns {Array} Returns the new empty array.
15980      * @example
15981      *
15982      * var arrays = _.times(2, _.stubArray);
15983      *
15984      * console.log(arrays);
15985      * // => [[], []]
15986      *
15987      * console.log(arrays[0] === arrays[1]);
15988      * // => false
15989      */
15990     function stubArray() {
15991       return [];
15992     }
15993
15994     /**
15995      * This method returns `false`.
15996      *
15997      * @static
15998      * @memberOf _
15999      * @since 4.13.0
16000      * @category Util
16001      * @returns {boolean} Returns `false`.
16002      * @example
16003      *
16004      * _.times(2, _.stubFalse);
16005      * // => [false, false]
16006      */
16007     function stubFalse() {
16008       return false;
16009     }
16010
16011     /**
16012      * This method returns a new empty object.
16013      *
16014      * @static
16015      * @memberOf _
16016      * @since 4.13.0
16017      * @category Util
16018      * @returns {Object} Returns the new empty object.
16019      * @example
16020      *
16021      * var objects = _.times(2, _.stubObject);
16022      *
16023      * console.log(objects);
16024      * // => [{}, {}]
16025      *
16026      * console.log(objects[0] === objects[1]);
16027      * // => false
16028      */
16029     function stubObject() {
16030       return {};
16031     }
16032
16033     /**
16034      * This method returns an empty string.
16035      *
16036      * @static
16037      * @memberOf _
16038      * @since 4.13.0
16039      * @category Util
16040      * @returns {string} Returns the empty string.
16041      * @example
16042      *
16043      * _.times(2, _.stubString);
16044      * // => ['', '']
16045      */
16046     function stubString() {
16047       return '';
16048     }
16049
16050     /**
16051      * This method returns `true`.
16052      *
16053      * @static
16054      * @memberOf _
16055      * @since 4.13.0
16056      * @category Util
16057      * @returns {boolean} Returns `true`.
16058      * @example
16059      *
16060      * _.times(2, _.stubTrue);
16061      * // => [true, true]
16062      */
16063     function stubTrue() {
16064       return true;
16065     }
16066
16067     /**
16068      * Invokes the iteratee `n` times, returning an array of the results of
16069      * each invocation. The iteratee is invoked with one argument; (index).
16070      *
16071      * @static
16072      * @since 0.1.0
16073      * @memberOf _
16074      * @category Util
16075      * @param {number} n The number of times to invoke `iteratee`.
16076      * @param {Function} [iteratee=_.identity] The function invoked per iteration.
16077      * @returns {Array} Returns the array of results.
16078      * @example
16079      *
16080      * _.times(3, String);
16081      * // => ['0', '1', '2']
16082      *
16083      *  _.times(4, _.constant(0));
16084      * // => [0, 0, 0, 0]
16085      */
16086     function times(n, iteratee) {
16087       n = toInteger(n);
16088       if (n < 1 || n > MAX_SAFE_INTEGER) {
16089         return [];
16090       }
16091       var index = MAX_ARRAY_LENGTH,
16092           length = nativeMin(n, MAX_ARRAY_LENGTH);
16093
16094       iteratee = getIteratee(iteratee);
16095       n -= MAX_ARRAY_LENGTH;
16096
16097       var result = baseTimes(length, iteratee);
16098       while (++index < n) {
16099         iteratee(index);
16100       }
16101       return result;
16102     }
16103
16104     /**
16105      * Converts `value` to a property path array.
16106      *
16107      * @static
16108      * @memberOf _
16109      * @since 4.0.0
16110      * @category Util
16111      * @param {*} value The value to convert.
16112      * @returns {Array} Returns the new property path array.
16113      * @example
16114      *
16115      * _.toPath('a.b.c');
16116      * // => ['a', 'b', 'c']
16117      *
16118      * _.toPath('a[0].b.c');
16119      * // => ['a', '0', 'b', 'c']
16120      */
16121     function toPath(value) {
16122       if (isArray(value)) {
16123         return arrayMap(value, toKey);
16124       }
16125       return isSymbol(value) ? [value] : copyArray(stringToPath(value));
16126     }
16127
16128     /**
16129      * Generates a unique ID. If `prefix` is given, the ID is appended to it.
16130      *
16131      * @static
16132      * @since 0.1.0
16133      * @memberOf _
16134      * @category Util
16135      * @param {string} [prefix=''] The value to prefix the ID with.
16136      * @returns {string} Returns the unique ID.
16137      * @example
16138      *
16139      * _.uniqueId('contact_');
16140      * // => 'contact_104'
16141      *
16142      * _.uniqueId();
16143      * // => '105'
16144      */
16145     function uniqueId(prefix) {
16146       var id = ++idCounter;
16147       return toString(prefix) + id;
16148     }
16149
16150     /*------------------------------------------------------------------------*/
16151
16152     /**
16153      * Adds two numbers.
16154      *
16155      * @static
16156      * @memberOf _
16157      * @since 3.4.0
16158      * @category Math
16159      * @param {number} augend The first number in an addition.
16160      * @param {number} addend The second number in an addition.
16161      * @returns {number} Returns the total.
16162      * @example
16163      *
16164      * _.add(6, 4);
16165      * // => 10
16166      */
16167     var add = createMathOperation(function(augend, addend) {
16168       return augend + addend;
16169     }, 0);
16170
16171     /**
16172      * Computes `number` rounded up to `precision`.
16173      *
16174      * @static
16175      * @memberOf _
16176      * @since 3.10.0
16177      * @category Math
16178      * @param {number} number The number to round up.
16179      * @param {number} [precision=0] The precision to round up to.
16180      * @returns {number} Returns the rounded up number.
16181      * @example
16182      *
16183      * _.ceil(4.006);
16184      * // => 5
16185      *
16186      * _.ceil(6.004, 2);
16187      * // => 6.01
16188      *
16189      * _.ceil(6040, -2);
16190      * // => 6100
16191      */
16192     var ceil = createRound('ceil');
16193
16194     /**
16195      * Divide two numbers.
16196      *
16197      * @static
16198      * @memberOf _
16199      * @since 4.7.0
16200      * @category Math
16201      * @param {number} dividend The first number in a division.
16202      * @param {number} divisor The second number in a division.
16203      * @returns {number} Returns the quotient.
16204      * @example
16205      *
16206      * _.divide(6, 4);
16207      * // => 1.5
16208      */
16209     var divide = createMathOperation(function(dividend, divisor) {
16210       return dividend / divisor;
16211     }, 1);
16212
16213     /**
16214      * Computes `number` rounded down to `precision`.
16215      *
16216      * @static
16217      * @memberOf _
16218      * @since 3.10.0
16219      * @category Math
16220      * @param {number} number The number to round down.
16221      * @param {number} [precision=0] The precision to round down to.
16222      * @returns {number} Returns the rounded down number.
16223      * @example
16224      *
16225      * _.floor(4.006);
16226      * // => 4
16227      *
16228      * _.floor(0.046, 2);
16229      * // => 0.04
16230      *
16231      * _.floor(4060, -2);
16232      * // => 4000
16233      */
16234     var floor = createRound('floor');
16235
16236     /**
16237      * Computes the maximum value of `array`. If `array` is empty or falsey,
16238      * `undefined` is returned.
16239      *
16240      * @static
16241      * @since 0.1.0
16242      * @memberOf _
16243      * @category Math
16244      * @param {Array} array The array to iterate over.
16245      * @returns {*} Returns the maximum value.
16246      * @example
16247      *
16248      * _.max([4, 2, 8, 6]);
16249      * // => 8
16250      *
16251      * _.max([]);
16252      * // => undefined
16253      */
16254     function max(array) {
16255       return (array && array.length)
16256         ? baseExtremum(array, identity, baseGt)
16257         : undefined;
16258     }
16259
16260     /**
16261      * This method is like `_.max` except that it accepts `iteratee` which is
16262      * invoked for each element in `array` to generate the criterion by which
16263      * the value is ranked. The iteratee is invoked with one argument: (value).
16264      *
16265      * @static
16266      * @memberOf _
16267      * @since 4.0.0
16268      * @category Math
16269      * @param {Array} array The array to iterate over.
16270      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16271      * @returns {*} Returns the maximum value.
16272      * @example
16273      *
16274      * var objects = [{ 'n': 1 }, { 'n': 2 }];
16275      *
16276      * _.maxBy(objects, function(o) { return o.n; });
16277      * // => { 'n': 2 }
16278      *
16279      * // The `_.property` iteratee shorthand.
16280      * _.maxBy(objects, 'n');
16281      * // => { 'n': 2 }
16282      */
16283     function maxBy(array, iteratee) {
16284       return (array && array.length)
16285         ? baseExtremum(array, getIteratee(iteratee, 2), baseGt)
16286         : undefined;
16287     }
16288
16289     /**
16290      * Computes the mean of the values in `array`.
16291      *
16292      * @static
16293      * @memberOf _
16294      * @since 4.0.0
16295      * @category Math
16296      * @param {Array} array The array to iterate over.
16297      * @returns {number} Returns the mean.
16298      * @example
16299      *
16300      * _.mean([4, 2, 8, 6]);
16301      * // => 5
16302      */
16303     function mean(array) {
16304       return baseMean(array, identity);
16305     }
16306
16307     /**
16308      * This method is like `_.mean` except that it accepts `iteratee` which is
16309      * invoked for each element in `array` to generate the value to be averaged.
16310      * The iteratee is invoked with one argument: (value).
16311      *
16312      * @static
16313      * @memberOf _
16314      * @since 4.7.0
16315      * @category Math
16316      * @param {Array} array The array to iterate over.
16317      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16318      * @returns {number} Returns the mean.
16319      * @example
16320      *
16321      * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
16322      *
16323      * _.meanBy(objects, function(o) { return o.n; });
16324      * // => 5
16325      *
16326      * // The `_.property` iteratee shorthand.
16327      * _.meanBy(objects, 'n');
16328      * // => 5
16329      */
16330     function meanBy(array, iteratee) {
16331       return baseMean(array, getIteratee(iteratee, 2));
16332     }
16333
16334     /**
16335      * Computes the minimum value of `array`. If `array` is empty or falsey,
16336      * `undefined` is returned.
16337      *
16338      * @static
16339      * @since 0.1.0
16340      * @memberOf _
16341      * @category Math
16342      * @param {Array} array The array to iterate over.
16343      * @returns {*} Returns the minimum value.
16344      * @example
16345      *
16346      * _.min([4, 2, 8, 6]);
16347      * // => 2
16348      *
16349      * _.min([]);
16350      * // => undefined
16351      */
16352     function min(array) {
16353       return (array && array.length)
16354         ? baseExtremum(array, identity, baseLt)
16355         : undefined;
16356     }
16357
16358     /**
16359      * This method is like `_.min` except that it accepts `iteratee` which is
16360      * invoked for each element in `array` to generate the criterion by which
16361      * the value is ranked. The iteratee is invoked with one argument: (value).
16362      *
16363      * @static
16364      * @memberOf _
16365      * @since 4.0.0
16366      * @category Math
16367      * @param {Array} array The array to iterate over.
16368      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16369      * @returns {*} Returns the minimum value.
16370      * @example
16371      *
16372      * var objects = [{ 'n': 1 }, { 'n': 2 }];
16373      *
16374      * _.minBy(objects, function(o) { return o.n; });
16375      * // => { 'n': 1 }
16376      *
16377      * // The `_.property` iteratee shorthand.
16378      * _.minBy(objects, 'n');
16379      * // => { 'n': 1 }
16380      */
16381     function minBy(array, iteratee) {
16382       return (array && array.length)
16383         ? baseExtremum(array, getIteratee(iteratee, 2), baseLt)
16384         : undefined;
16385     }
16386
16387     /**
16388      * Multiply two numbers.
16389      *
16390      * @static
16391      * @memberOf _
16392      * @since 4.7.0
16393      * @category Math
16394      * @param {number} multiplier The first number in a multiplication.
16395      * @param {number} multiplicand The second number in a multiplication.
16396      * @returns {number} Returns the product.
16397      * @example
16398      *
16399      * _.multiply(6, 4);
16400      * // => 24
16401      */
16402     var multiply = createMathOperation(function(multiplier, multiplicand) {
16403       return multiplier * multiplicand;
16404     }, 1);
16405
16406     /**
16407      * Computes `number` rounded to `precision`.
16408      *
16409      * @static
16410      * @memberOf _
16411      * @since 3.10.0
16412      * @category Math
16413      * @param {number} number The number to round.
16414      * @param {number} [precision=0] The precision to round to.
16415      * @returns {number} Returns the rounded number.
16416      * @example
16417      *
16418      * _.round(4.006);
16419      * // => 4
16420      *
16421      * _.round(4.006, 2);
16422      * // => 4.01
16423      *
16424      * _.round(4060, -2);
16425      * // => 4100
16426      */
16427     var round = createRound('round');
16428
16429     /**
16430      * Subtract two numbers.
16431      *
16432      * @static
16433      * @memberOf _
16434      * @since 4.0.0
16435      * @category Math
16436      * @param {number} minuend The first number in a subtraction.
16437      * @param {number} subtrahend The second number in a subtraction.
16438      * @returns {number} Returns the difference.
16439      * @example
16440      *
16441      * _.subtract(6, 4);
16442      * // => 2
16443      */
16444     var subtract = createMathOperation(function(minuend, subtrahend) {
16445       return minuend - subtrahend;
16446     }, 0);
16447
16448     /**
16449      * Computes the sum of the values in `array`.
16450      *
16451      * @static
16452      * @memberOf _
16453      * @since 3.4.0
16454      * @category Math
16455      * @param {Array} array The array to iterate over.
16456      * @returns {number} Returns the sum.
16457      * @example
16458      *
16459      * _.sum([4, 2, 8, 6]);
16460      * // => 20
16461      */
16462     function sum(array) {
16463       return (array && array.length)
16464         ? baseSum(array, identity)
16465         : 0;
16466     }
16467
16468     /**
16469      * This method is like `_.sum` except that it accepts `iteratee` which is
16470      * invoked for each element in `array` to generate the value to be summed.
16471      * The iteratee is invoked with one argument: (value).
16472      *
16473      * @static
16474      * @memberOf _
16475      * @since 4.0.0
16476      * @category Math
16477      * @param {Array} array The array to iterate over.
16478      * @param {Function} [iteratee=_.identity] The iteratee invoked per element.
16479      * @returns {number} Returns the sum.
16480      * @example
16481      *
16482      * var objects = [{ 'n': 4 }, { 'n': 2 }, { 'n': 8 }, { 'n': 6 }];
16483      *
16484      * _.sumBy(objects, function(o) { return o.n; });
16485      * // => 20
16486      *
16487      * // The `_.property` iteratee shorthand.
16488      * _.sumBy(objects, 'n');
16489      * // => 20
16490      */
16491     function sumBy(array, iteratee) {
16492       return (array && array.length)
16493         ? baseSum(array, getIteratee(iteratee, 2))
16494         : 0;
16495     }
16496
16497     /*------------------------------------------------------------------------*/
16498
16499     // Add methods that return wrapped values in chain sequences.
16500     lodash.after = after;
16501     lodash.ary = ary;
16502     lodash.assign = assign;
16503     lodash.assignIn = assignIn;
16504     lodash.assignInWith = assignInWith;
16505     lodash.assignWith = assignWith;
16506     lodash.at = at;
16507     lodash.before = before;
16508     lodash.bind = bind;
16509     lodash.bindAll = bindAll;
16510     lodash.bindKey = bindKey;
16511     lodash.castArray = castArray;
16512     lodash.chain = chain;
16513     lodash.chunk = chunk;
16514     lodash.compact = compact;
16515     lodash.concat = concat;
16516     lodash.cond = cond;
16517     lodash.conforms = conforms;
16518     lodash.constant = constant;
16519     lodash.countBy = countBy;
16520     lodash.create = create;
16521     lodash.curry = curry;
16522     lodash.curryRight = curryRight;
16523     lodash.debounce = debounce;
16524     lodash.defaults = defaults;
16525     lodash.defaultsDeep = defaultsDeep;
16526     lodash.defer = defer;
16527     lodash.delay = delay;
16528     lodash.difference = difference;
16529     lodash.differenceBy = differenceBy;
16530     lodash.differenceWith = differenceWith;
16531     lodash.drop = drop;
16532     lodash.dropRight = dropRight;
16533     lodash.dropRightWhile = dropRightWhile;
16534     lodash.dropWhile = dropWhile;
16535     lodash.fill = fill;
16536     lodash.filter = filter;
16537     lodash.flatMap = flatMap;
16538     lodash.flatMapDeep = flatMapDeep;
16539     lodash.flatMapDepth = flatMapDepth;
16540     lodash.flatten = flatten;
16541     lodash.flattenDeep = flattenDeep;
16542     lodash.flattenDepth = flattenDepth;
16543     lodash.flip = flip;
16544     lodash.flow = flow;
16545     lodash.flowRight = flowRight;
16546     lodash.fromPairs = fromPairs;
16547     lodash.functions = functions;
16548     lodash.functionsIn = functionsIn;
16549     lodash.groupBy = groupBy;
16550     lodash.initial = initial;
16551     lodash.intersection = intersection;
16552     lodash.intersectionBy = intersectionBy;
16553     lodash.intersectionWith = intersectionWith;
16554     lodash.invert = invert;
16555     lodash.invertBy = invertBy;
16556     lodash.invokeMap = invokeMap;
16557     lodash.iteratee = iteratee;
16558     lodash.keyBy = keyBy;
16559     lodash.keys = keys;
16560     lodash.keysIn = keysIn;
16561     lodash.map = map;
16562     lodash.mapKeys = mapKeys;
16563     lodash.mapValues = mapValues;
16564     lodash.matches = matches;
16565     lodash.matchesProperty = matchesProperty;
16566     lodash.memoize = memoize;
16567     lodash.merge = merge;
16568     lodash.mergeWith = mergeWith;
16569     lodash.method = method;
16570     lodash.methodOf = methodOf;
16571     lodash.mixin = mixin;
16572     lodash.negate = negate;
16573     lodash.nthArg = nthArg;
16574     lodash.omit = omit;
16575     lodash.omitBy = omitBy;
16576     lodash.once = once;
16577     lodash.orderBy = orderBy;
16578     lodash.over = over;
16579     lodash.overArgs = overArgs;
16580     lodash.overEvery = overEvery;
16581     lodash.overSome = overSome;
16582     lodash.partial = partial;
16583     lodash.partialRight = partialRight;
16584     lodash.partition = partition;
16585     lodash.pick = pick;
16586     lodash.pickBy = pickBy;
16587     lodash.property = property;
16588     lodash.propertyOf = propertyOf;
16589     lodash.pull = pull;
16590     lodash.pullAll = pullAll;
16591     lodash.pullAllBy = pullAllBy;
16592     lodash.pullAllWith = pullAllWith;
16593     lodash.pullAt = pullAt;
16594     lodash.range = range;
16595     lodash.rangeRight = rangeRight;
16596     lodash.rearg = rearg;
16597     lodash.reject = reject;
16598     lodash.remove = remove;
16599     lodash.rest = rest;
16600     lodash.reverse = reverse;
16601     lodash.sampleSize = sampleSize;
16602     lodash.set = set;
16603     lodash.setWith = setWith;
16604     lodash.shuffle = shuffle;
16605     lodash.slice = slice;
16606     lodash.sortBy = sortBy;
16607     lodash.sortedUniq = sortedUniq;
16608     lodash.sortedUniqBy = sortedUniqBy;
16609     lodash.split = split;
16610     lodash.spread = spread;
16611     lodash.tail = tail;
16612     lodash.take = take;
16613     lodash.takeRight = takeRight;
16614     lodash.takeRightWhile = takeRightWhile;
16615     lodash.takeWhile = takeWhile;
16616     lodash.tap = tap;
16617     lodash.throttle = throttle;
16618     lodash.thru = thru;
16619     lodash.toArray = toArray;
16620     lodash.toPairs = toPairs;
16621     lodash.toPairsIn = toPairsIn;
16622     lodash.toPath = toPath;
16623     lodash.toPlainObject = toPlainObject;
16624     lodash.transform = transform;
16625     lodash.unary = unary;
16626     lodash.union = union;
16627     lodash.unionBy = unionBy;
16628     lodash.unionWith = unionWith;
16629     lodash.uniq = uniq;
16630     lodash.uniqBy = uniqBy;
16631     lodash.uniqWith = uniqWith;
16632     lodash.unset = unset;
16633     lodash.unzip = unzip;
16634     lodash.unzipWith = unzipWith;
16635     lodash.update = update;
16636     lodash.updateWith = updateWith;
16637     lodash.values = values;
16638     lodash.valuesIn = valuesIn;
16639     lodash.without = without;
16640     lodash.words = words;
16641     lodash.wrap = wrap;
16642     lodash.xor = xor;
16643     lodash.xorBy = xorBy;
16644     lodash.xorWith = xorWith;
16645     lodash.zip = zip;
16646     lodash.zipObject = zipObject;
16647     lodash.zipObjectDeep = zipObjectDeep;
16648     lodash.zipWith = zipWith;
16649
16650     // Add aliases.
16651     lodash.entries = toPairs;
16652     lodash.entriesIn = toPairsIn;
16653     lodash.extend = assignIn;
16654     lodash.extendWith = assignInWith;
16655
16656     // Add methods to `lodash.prototype`.
16657     mixin(lodash, lodash);
16658
16659     /*------------------------------------------------------------------------*/
16660
16661     // Add methods that return unwrapped values in chain sequences.
16662     lodash.add = add;
16663     lodash.attempt = attempt;
16664     lodash.camelCase = camelCase;
16665     lodash.capitalize = capitalize;
16666     lodash.ceil = ceil;
16667     lodash.clamp = clamp;
16668     lodash.clone = clone;
16669     lodash.cloneDeep = cloneDeep;
16670     lodash.cloneDeepWith = cloneDeepWith;
16671     lodash.cloneWith = cloneWith;
16672     lodash.conformsTo = conformsTo;
16673     lodash.deburr = deburr;
16674     lodash.defaultTo = defaultTo;
16675     lodash.divide = divide;
16676     lodash.endsWith = endsWith;
16677     lodash.eq = eq;
16678     lodash.escape = escape;
16679     lodash.escapeRegExp = escapeRegExp;
16680     lodash.every = every;
16681     lodash.find = find;
16682     lodash.findIndex = findIndex;
16683     lodash.findKey = findKey;
16684     lodash.findLast = findLast;
16685     lodash.findLastIndex = findLastIndex;
16686     lodash.findLastKey = findLastKey;
16687     lodash.floor = floor;
16688     lodash.forEach = forEach;
16689     lodash.forEachRight = forEachRight;
16690     lodash.forIn = forIn;
16691     lodash.forInRight = forInRight;
16692     lodash.forOwn = forOwn;
16693     lodash.forOwnRight = forOwnRight;
16694     lodash.get = get;
16695     lodash.gt = gt;
16696     lodash.gte = gte;
16697     lodash.has = has;
16698     lodash.hasIn = hasIn;
16699     lodash.head = head;
16700     lodash.identity = identity;
16701     lodash.includes = includes;
16702     lodash.indexOf = indexOf;
16703     lodash.inRange = inRange;
16704     lodash.invoke = invoke;
16705     lodash.isArguments = isArguments;
16706     lodash.isArray = isArray;
16707     lodash.isArrayBuffer = isArrayBuffer;
16708     lodash.isArrayLike = isArrayLike;
16709     lodash.isArrayLikeObject = isArrayLikeObject;
16710     lodash.isBoolean = isBoolean;
16711     lodash.isBuffer = isBuffer;
16712     lodash.isDate = isDate;
16713     lodash.isElement = isElement;
16714     lodash.isEmpty = isEmpty;
16715     lodash.isEqual = isEqual;
16716     lodash.isEqualWith = isEqualWith;
16717     lodash.isError = isError;
16718     lodash.isFinite = isFinite;
16719     lodash.isFunction = isFunction;
16720     lodash.isInteger = isInteger;
16721     lodash.isLength = isLength;
16722     lodash.isMap = isMap;
16723     lodash.isMatch = isMatch;
16724     lodash.isMatchWith = isMatchWith;
16725     lodash.isNaN = isNaN;
16726     lodash.isNative = isNative;
16727     lodash.isNil = isNil;
16728     lodash.isNull = isNull;
16729     lodash.isNumber = isNumber;
16730     lodash.isObject = isObject;
16731     lodash.isObjectLike = isObjectLike;
16732     lodash.isPlainObject = isPlainObject;
16733     lodash.isRegExp = isRegExp;
16734     lodash.isSafeInteger = isSafeInteger;
16735     lodash.isSet = isSet;
16736     lodash.isString = isString;
16737     lodash.isSymbol = isSymbol;
16738     lodash.isTypedArray = isTypedArray;
16739     lodash.isUndefined = isUndefined;
16740     lodash.isWeakMap = isWeakMap;
16741     lodash.isWeakSet = isWeakSet;
16742     lodash.join = join;
16743     lodash.kebabCase = kebabCase;
16744     lodash.last = last;
16745     lodash.lastIndexOf = lastIndexOf;
16746     lodash.lowerCase = lowerCase;
16747     lodash.lowerFirst = lowerFirst;
16748     lodash.lt = lt;
16749     lodash.lte = lte;
16750     lodash.max = max;
16751     lodash.maxBy = maxBy;
16752     lodash.mean = mean;
16753     lodash.meanBy = meanBy;
16754     lodash.min = min;
16755     lodash.minBy = minBy;
16756     lodash.stubArray = stubArray;
16757     lodash.stubFalse = stubFalse;
16758     lodash.stubObject = stubObject;
16759     lodash.stubString = stubString;
16760     lodash.stubTrue = stubTrue;
16761     lodash.multiply = multiply;
16762     lodash.nth = nth;
16763     lodash.noConflict = noConflict;
16764     lodash.noop = noop;
16765     lodash.now = now;
16766     lodash.pad = pad;
16767     lodash.padEnd = padEnd;
16768     lodash.padStart = padStart;
16769     lodash.parseInt = parseInt;
16770     lodash.random = random;
16771     lodash.reduce = reduce;
16772     lodash.reduceRight = reduceRight;
16773     lodash.repeat = repeat;
16774     lodash.replace = replace;
16775     lodash.result = result;
16776     lodash.round = round;
16777     lodash.runInContext = runInContext;
16778     lodash.sample = sample;
16779     lodash.size = size;
16780     lodash.snakeCase = snakeCase;
16781     lodash.some = some;
16782     lodash.sortedIndex = sortedIndex;
16783     lodash.sortedIndexBy = sortedIndexBy;
16784     lodash.sortedIndexOf = sortedIndexOf;
16785     lodash.sortedLastIndex = sortedLastIndex;
16786     lodash.sortedLastIndexBy = sortedLastIndexBy;
16787     lodash.sortedLastIndexOf = sortedLastIndexOf;
16788     lodash.startCase = startCase;
16789     lodash.startsWith = startsWith;
16790     lodash.subtract = subtract;
16791     lodash.sum = sum;
16792     lodash.sumBy = sumBy;
16793     lodash.template = template;
16794     lodash.times = times;
16795     lodash.toFinite = toFinite;
16796     lodash.toInteger = toInteger;
16797     lodash.toLength = toLength;
16798     lodash.toLower = toLower;
16799     lodash.toNumber = toNumber;
16800     lodash.toSafeInteger = toSafeInteger;
16801     lodash.toString = toString;
16802     lodash.toUpper = toUpper;
16803     lodash.trim = trim;
16804     lodash.trimEnd = trimEnd;
16805     lodash.trimStart = trimStart;
16806     lodash.truncate = truncate;
16807     lodash.unescape = unescape;
16808     lodash.uniqueId = uniqueId;
16809     lodash.upperCase = upperCase;
16810     lodash.upperFirst = upperFirst;
16811
16812     // Add aliases.
16813     lodash.each = forEach;
16814     lodash.eachRight = forEachRight;
16815     lodash.first = head;
16816
16817     mixin(lodash, (function() {
16818       var source = {};
16819       baseForOwn(lodash, function(func, methodName) {
16820         if (!hasOwnProperty.call(lodash.prototype, methodName)) {
16821           source[methodName] = func;
16822         }
16823       });
16824       return source;
16825     }()), { 'chain': false });
16826
16827     /*------------------------------------------------------------------------*/
16828
16829     /**
16830      * The semantic version number.
16831      *
16832      * @static
16833      * @memberOf _
16834      * @type {string}
16835      */
16836     lodash.VERSION = VERSION;
16837
16838     // Assign default placeholders.
16839     arrayEach(['bind', 'bindKey', 'curry', 'curryRight', 'partial', 'partialRight'], function(methodName) {
16840       lodash[methodName].placeholder = lodash;
16841     });
16842
16843     // Add `LazyWrapper` methods for `_.drop` and `_.take` variants.
16844     arrayEach(['drop', 'take'], function(methodName, index) {
16845       LazyWrapper.prototype[methodName] = function(n) {
16846         var filtered = this.__filtered__;
16847         if (filtered && !index) {
16848           return new LazyWrapper(this);
16849         }
16850         n = n === undefined ? 1 : nativeMax(toInteger(n), 0);
16851
16852         var result = this.clone();
16853         if (filtered) {
16854           result.__takeCount__ = nativeMin(n, result.__takeCount__);
16855         } else {
16856           result.__views__.push({
16857             'size': nativeMin(n, MAX_ARRAY_LENGTH),
16858             'type': methodName + (result.__dir__ < 0 ? 'Right' : '')
16859           });
16860         }
16861         return result;
16862       };
16863
16864       LazyWrapper.prototype[methodName + 'Right'] = function(n) {
16865         return this.reverse()[methodName](n).reverse();
16866       };
16867     });
16868
16869     // Add `LazyWrapper` methods that accept an `iteratee` value.
16870     arrayEach(['filter', 'map', 'takeWhile'], function(methodName, index) {
16871       var type = index + 1,
16872           isFilter = type == LAZY_FILTER_FLAG || type == LAZY_WHILE_FLAG;
16873
16874       LazyWrapper.prototype[methodName] = function(iteratee) {
16875         var result = this.clone();
16876         result.__iteratees__.push({
16877           'iteratee': getIteratee(iteratee, 3),
16878           'type': type
16879         });
16880         result.__filtered__ = result.__filtered__ || isFilter;
16881         return result;
16882       };
16883     });
16884
16885     // Add `LazyWrapper` methods for `_.head` and `_.last`.
16886     arrayEach(['head', 'last'], function(methodName, index) {
16887       var takeName = 'take' + (index ? 'Right' : '');
16888
16889       LazyWrapper.prototype[methodName] = function() {
16890         return this[takeName](1).value()[0];
16891       };
16892     });
16893
16894     // Add `LazyWrapper` methods for `_.initial` and `_.tail`.
16895     arrayEach(['initial', 'tail'], function(methodName, index) {
16896       var dropName = 'drop' + (index ? '' : 'Right');
16897
16898       LazyWrapper.prototype[methodName] = function() {
16899         return this.__filtered__ ? new LazyWrapper(this) : this[dropName](1);
16900       };
16901     });
16902
16903     LazyWrapper.prototype.compact = function() {
16904       return this.filter(identity);
16905     };
16906
16907     LazyWrapper.prototype.find = function(predicate) {
16908       return this.filter(predicate).head();
16909     };
16910
16911     LazyWrapper.prototype.findLast = function(predicate) {
16912       return this.reverse().find(predicate);
16913     };
16914
16915     LazyWrapper.prototype.invokeMap = baseRest(function(path, args) {
16916       if (typeof path == 'function') {
16917         return new LazyWrapper(this);
16918       }
16919       return this.map(function(value) {
16920         return baseInvoke(value, path, args);
16921       });
16922     });
16923
16924     LazyWrapper.prototype.reject = function(predicate) {
16925       return this.filter(negate(getIteratee(predicate)));
16926     };
16927
16928     LazyWrapper.prototype.slice = function(start, end) {
16929       start = toInteger(start);
16930
16931       var result = this;
16932       if (result.__filtered__ && (start > 0 || end < 0)) {
16933         return new LazyWrapper(result);
16934       }
16935       if (start < 0) {
16936         result = result.takeRight(-start);
16937       } else if (start) {
16938         result = result.drop(start);
16939       }
16940       if (end !== undefined) {
16941         end = toInteger(end);
16942         result = end < 0 ? result.dropRight(-end) : result.take(end - start);
16943       }
16944       return result;
16945     };
16946
16947     LazyWrapper.prototype.takeRightWhile = function(predicate) {
16948       return this.reverse().takeWhile(predicate).reverse();
16949     };
16950
16951     LazyWrapper.prototype.toArray = function() {
16952       return this.take(MAX_ARRAY_LENGTH);
16953     };
16954
16955     // Add `LazyWrapper` methods to `lodash.prototype`.
16956     baseForOwn(LazyWrapper.prototype, function(func, methodName) {
16957       var checkIteratee = /^(?:filter|find|map|reject)|While$/.test(methodName),
16958           isTaker = /^(?:head|last)$/.test(methodName),
16959           lodashFunc = lodash[isTaker ? ('take' + (methodName == 'last' ? 'Right' : '')) : methodName],
16960           retUnwrapped = isTaker || /^find/.test(methodName);
16961
16962       if (!lodashFunc) {
16963         return;
16964       }
16965       lodash.prototype[methodName] = function() {
16966         var value = this.__wrapped__,
16967             args = isTaker ? [1] : arguments,
16968             isLazy = value instanceof LazyWrapper,
16969             iteratee = args[0],
16970             useLazy = isLazy || isArray(value);
16971
16972         var interceptor = function(value) {
16973           var result = lodashFunc.apply(lodash, arrayPush([value], args));
16974           return (isTaker && chainAll) ? result[0] : result;
16975         };
16976
16977         if (useLazy && checkIteratee && typeof iteratee == 'function' && iteratee.length != 1) {
16978           // Avoid lazy use if the iteratee has a "length" value other than `1`.
16979           isLazy = useLazy = false;
16980         }
16981         var chainAll = this.__chain__,
16982             isHybrid = !!this.__actions__.length,
16983             isUnwrapped = retUnwrapped && !chainAll,
16984             onlyLazy = isLazy && !isHybrid;
16985
16986         if (!retUnwrapped && useLazy) {
16987           value = onlyLazy ? value : new LazyWrapper(this);
16988           var result = func.apply(value, args);
16989           result.__actions__.push({ 'func': thru, 'args': [interceptor], 'thisArg': undefined });
16990           return new LodashWrapper(result, chainAll);
16991         }
16992         if (isUnwrapped && onlyLazy) {
16993           return func.apply(this, args);
16994         }
16995         result = this.thru(interceptor);
16996         return isUnwrapped ? (isTaker ? result.value()[0] : result.value()) : result;
16997       };
16998     });
16999
17000     // Add `Array` methods to `lodash.prototype`.
17001     arrayEach(['pop', 'push', 'shift', 'sort', 'splice', 'unshift'], function(methodName) {
17002       var func = arrayProto[methodName],
17003           chainName = /^(?:push|sort|unshift)$/.test(methodName) ? 'tap' : 'thru',
17004           retUnwrapped = /^(?:pop|shift)$/.test(methodName);
17005
17006       lodash.prototype[methodName] = function() {
17007         var args = arguments;
17008         if (retUnwrapped && !this.__chain__) {
17009           var value = this.value();
17010           return func.apply(isArray(value) ? value : [], args);
17011         }
17012         return this[chainName](function(value) {
17013           return func.apply(isArray(value) ? value : [], args);
17014         });
17015       };
17016     });
17017
17018     // Map minified method names to their real names.
17019     baseForOwn(LazyWrapper.prototype, function(func, methodName) {
17020       var lodashFunc = lodash[methodName];
17021       if (lodashFunc) {
17022         var key = (lodashFunc.name + ''),
17023             names = realNames[key] || (realNames[key] = []);
17024
17025         names.push({ 'name': methodName, 'func': lodashFunc });
17026       }
17027     });
17028
17029     realNames[createHybrid(undefined, WRAP_BIND_KEY_FLAG).name] = [{
17030       'name': 'wrapper',
17031       'func': undefined
17032     }];
17033
17034     // Add methods to `LazyWrapper`.
17035     LazyWrapper.prototype.clone = lazyClone;
17036     LazyWrapper.prototype.reverse = lazyReverse;
17037     LazyWrapper.prototype.value = lazyValue;
17038
17039     // Add chain sequence methods to the `lodash` wrapper.
17040     lodash.prototype.at = wrapperAt;
17041     lodash.prototype.chain = wrapperChain;
17042     lodash.prototype.commit = wrapperCommit;
17043     lodash.prototype.next = wrapperNext;
17044     lodash.prototype.plant = wrapperPlant;
17045     lodash.prototype.reverse = wrapperReverse;
17046     lodash.prototype.toJSON = lodash.prototype.valueOf = lodash.prototype.value = wrapperValue;
17047
17048     // Add lazy aliases.
17049     lodash.prototype.first = lodash.prototype.head;
17050
17051     if (symIterator) {
17052       lodash.prototype[symIterator] = wrapperToIterator;
17053     }
17054     return lodash;
17055   });
17056
17057   /*--------------------------------------------------------------------------*/
17058
17059   // Export lodash.
17060   var _ = runInContext();
17061
17062   // Some AMD build optimizers, like r.js, check for condition patterns like:
17063   if (typeof define == 'function' && typeof define.amd == 'object' && define.amd) {
17064     // Expose Lodash on the global object to prevent errors when Lodash is
17065     // loaded by a script tag in the presence of an AMD loader.
17066     // See http://requirejs.org/docs/errors.html#mismatch for more details.
17067     // Use `_.noConflict` to remove Lodash from the global object.
17068     root._ = _;
17069
17070     // Define as an anonymous module so, through path mapping, it can be
17071     // referenced as the "underscore" module.
17072     define(function() {
17073       return _;
17074     });
17075   }
17076   // Check for `exports` after `define` in case a build optimizer adds it.
17077   else if (freeModule) {
17078     // Export for Node.js.
17079     (freeModule.exports = _)._ = _;
17080     // Export for CommonJS support.
17081     freeExports._ = _;
17082   }
17083   else {
17084     // Export to the global object.
17085     root._ = _;
17086   }
17087 }.call(commonjsGlobal));
17088 });
17089
17090 function osmIsInterestingTag(key) {
17091     return key !== 'attribution' &&
17092         key !== 'created_by' &&
17093         key !== 'source' &&
17094         key !== 'odbl' &&
17095         key.indexOf('tiger:') !== 0;
17096
17097 }
17098
17099
17100 var osmOneWayTags = {
17101     'aerialway': {
17102         'chair_lift': true,
17103         'mixed_lift': true,
17104         't-bar': true,
17105         'j-bar': true,
17106         'platter': true,
17107         'rope_tow': true,
17108         'magic_carpet': true,
17109         'yes': true
17110     },
17111     'highway': {
17112         'motorway': true,
17113         'motorway_link': true
17114     },
17115     'junction': {
17116         'roundabout': true
17117     },
17118     'man_made': {
17119         'piste:halfpipe': true
17120     },
17121     'piste:type': {
17122         'downhill': true,
17123         'sled': true,
17124         'yes': true
17125     },
17126     'waterway': {
17127         'river': true,
17128         'stream': true
17129     }
17130 };
17131
17132
17133 var osmPavedTags = {
17134     'surface': {
17135         'paved': true,
17136         'asphalt': true,
17137         'concrete': true
17138     },
17139     'tracktype': {
17140         'grade1': true
17141     }
17142 };
17143
17144 var dataWikipedia = [
17145     [
17146         "Abkhazian",
17147         "Аҧсшәа",
17148         "ab"
17149     ],
17150     [
17151         "Achinese",
17152         "Acèh",
17153         "ace"
17154     ],
17155     [
17156         "Adyghe",
17157         "адыгабзэ",
17158         "ady"
17159     ],
17160     [
17161         "Afrikaans",
17162         "Afrikaans",
17163         "af"
17164     ],
17165     [
17166         "Akan",
17167         "Akan",
17168         "ak"
17169     ],
17170     [
17171         "Alemannisch",
17172         "Alemannisch",
17173         "als"
17174     ],
17175     [
17176         "Amharic",
17177         "አማርኛ",
17178         "am"
17179     ],
17180     [
17181         "Aragonese",
17182         "aragonés",
17183         "an"
17184     ],
17185     [
17186         "Old English",
17187         "Ænglisc",
17188         "ang"
17189     ],
17190     [
17191         "Arabic",
17192         "العربية",
17193         "ar"
17194     ],
17195     [
17196         "Aramaic",
17197         "ܐܪܡܝܐ",
17198         "arc"
17199     ],
17200     [
17201         "Egyptian Arabic",
17202         "مصرى",
17203         "arz"
17204     ],
17205     [
17206         "Assamese",
17207         "অসমীয়া",
17208         "as"
17209     ],
17210     [
17211         "Asturian",
17212         "asturianu",
17213         "ast"
17214     ],
17215     [
17216         "Avaric",
17217         "авар",
17218         "av"
17219     ],
17220     [
17221         "Aymara",
17222         "Aymar aru",
17223         "ay"
17224     ],
17225     [
17226         "Azerbaijani",
17227         "azərbaycanca",
17228         "az"
17229     ],
17230     [
17231         "تۆرکجه",
17232         "تۆرکجه",
17233         "azb"
17234     ],
17235     [
17236         "Bashkir",
17237         "башҡортса",
17238         "ba"
17239     ],
17240     [
17241         "Bavarian",
17242         "Boarisch",
17243         "bar"
17244     ],
17245     [
17246         "Samogitian",
17247         "žemaitėška",
17248         "bat-smg"
17249     ],
17250     [
17251         "Bikol Central",
17252         "Bikol Central",
17253         "bcl"
17254     ],
17255     [
17256         "Belarusian",
17257         "беларуская",
17258         "be"
17259     ],
17260     [
17261         "беларуская (тарашкевіца)‎",
17262         "беларуская (тарашкевіца)‎",
17263         "be-x-old"
17264     ],
17265     [
17266         "Bulgarian",
17267         "български",
17268         "bg"
17269     ],
17270     [
17271         "भोजपुरी",
17272         "भोजपुरी",
17273         "bh"
17274     ],
17275     [
17276         "Bislama",
17277         "Bislama",
17278         "bi"
17279     ],
17280     [
17281         "Banjar",
17282         "Bahasa Banjar",
17283         "bjn"
17284     ],
17285     [
17286         "Bambara",
17287         "bamanankan",
17288         "bm"
17289     ],
17290     [
17291         "Bengali",
17292         "বাংলা",
17293         "bn"
17294     ],
17295     [
17296         "Tibetan",
17297         "བོད་ཡིག",
17298         "bo"
17299     ],
17300     [
17301         "Bishnupriya",
17302         "বিষ্ণুপ্রিয়া মণিপুরী",
17303         "bpy"
17304     ],
17305     [
17306         "Breton",
17307         "brezhoneg",
17308         "br"
17309     ],
17310     [
17311         "Bosnian",
17312         "bosanski",
17313         "bs"
17314     ],
17315     [
17316         "Buginese",
17317         "ᨅᨔ ᨕᨘᨁᨗ",
17318         "bug"
17319     ],
17320     [
17321         "буряад",
17322         "буряад",
17323         "bxr"
17324     ],
17325     [
17326         "Catalan",
17327         "català",
17328         "ca"
17329     ],
17330     [
17331         "Chavacano de Zamboanga",
17332         "Chavacano de Zamboanga",
17333         "cbk-zam"
17334     ],
17335     [
17336         "Min Dong Chinese",
17337         "Mìng-dĕ̤ng-ngṳ̄",
17338         "cdo"
17339     ],
17340     [
17341         "Chechen",
17342         "нохчийн",
17343         "ce"
17344     ],
17345     [
17346         "Cebuano",
17347         "Cebuano",
17348         "ceb"
17349     ],
17350     [
17351         "Chamorro",
17352         "Chamoru",
17353         "ch"
17354     ],
17355     [
17356         "Cherokee",
17357         "ᏣᎳᎩ",
17358         "chr"
17359     ],
17360     [
17361         "Cheyenne",
17362         "Tsetsêhestâhese",
17363         "chy"
17364     ],
17365     [
17366         "Central Kurdish",
17367         "کوردیی ناوەندی",
17368         "ckb"
17369     ],
17370     [
17371         "Corsican",
17372         "corsu",
17373         "co"
17374     ],
17375     [
17376         "Cree",
17377         "Nēhiyawēwin / ᓀᐦᐃᔭᐍᐏᐣ",
17378         "cr"
17379     ],
17380     [
17381         "Crimean Turkish",
17382         "qırımtatarca",
17383         "crh"
17384     ],
17385     [
17386         "Czech",
17387         "čeština",
17388         "cs"
17389     ],
17390     [
17391         "Kashubian",
17392         "kaszëbsczi",
17393         "csb"
17394     ],
17395     [
17396         "Church Slavic",
17397         "словѣньскъ / ⰔⰎⰑⰂⰡⰐⰠⰔⰍⰟ",
17398         "cu"
17399     ],
17400     [
17401         "Chuvash",
17402         "Чӑвашла",
17403         "cv"
17404     ],
17405     [
17406         "Welsh",
17407         "Cymraeg",
17408         "cy"
17409     ],
17410     [
17411         "Danish",
17412         "dansk",
17413         "da"
17414     ],
17415     [
17416         "German",
17417         "Deutsch",
17418         "de"
17419     ],
17420     [
17421         "Zazaki",
17422         "Zazaki",
17423         "diq"
17424     ],
17425     [
17426         "Lower Sorbian",
17427         "dolnoserbski",
17428         "dsb"
17429     ],
17430     [
17431         "Divehi",
17432         "ދިވެހިބަސް",
17433         "dv"
17434     ],
17435     [
17436         "Dzongkha",
17437         "ཇོང་ཁ",
17438         "dz"
17439     ],
17440     [
17441         "Ewe",
17442         "eʋegbe",
17443         "ee"
17444     ],
17445     [
17446         "Greek",
17447         "Ελληνικά",
17448         "el"
17449     ],
17450     [
17451         "Emiliano-Romagnolo",
17452         "emiliàn e rumagnòl",
17453         "eml"
17454     ],
17455     [
17456         "English",
17457         "English",
17458         "en"
17459     ],
17460     [
17461         "Esperanto",
17462         "Esperanto",
17463         "eo"
17464     ],
17465     [
17466         "Spanish",
17467         "español",
17468         "es"
17469     ],
17470     [
17471         "Estonian",
17472         "eesti",
17473         "et"
17474     ],
17475     [
17476         "Basque",
17477         "euskara",
17478         "eu"
17479     ],
17480     [
17481         "Extremaduran",
17482         "estremeñu",
17483         "ext"
17484     ],
17485     [
17486         "Persian",
17487         "فارسی",
17488         "fa"
17489     ],
17490     [
17491         "Fulah",
17492         "Fulfulde",
17493         "ff"
17494     ],
17495     [
17496         "Finnish",
17497         "suomi",
17498         "fi"
17499     ],
17500     [
17501         "Võro",
17502         "Võro",
17503         "fiu-vro"
17504     ],
17505     [
17506         "Fijian",
17507         "Na Vosa Vakaviti",
17508         "fj"
17509     ],
17510     [
17511         "Faroese",
17512         "føroyskt",
17513         "fo"
17514     ],
17515     [
17516         "French",
17517         "français",
17518         "fr"
17519     ],
17520     [
17521         "Arpitan",
17522         "arpetan",
17523         "frp"
17524     ],
17525     [
17526         "Northern Frisian",
17527         "Nordfriisk",
17528         "frr"
17529     ],
17530     [
17531         "Friulian",
17532         "furlan",
17533         "fur"
17534     ],
17535     [
17536         "Western Frisian",
17537         "Frysk",
17538         "fy"
17539     ],
17540     [
17541         "Irish",
17542         "Gaeilge",
17543         "ga"
17544     ],
17545     [
17546         "Gagauz",
17547         "Gagauz",
17548         "gag"
17549     ],
17550     [
17551         "Gan Chinese",
17552         "贛語",
17553         "gan"
17554     ],
17555     [
17556         "Scottish Gaelic",
17557         "Gàidhlig",
17558         "gd"
17559     ],
17560     [
17561         "Galician",
17562         "galego",
17563         "gl"
17564     ],
17565     [
17566         "Gilaki",
17567         "گیلکی",
17568         "glk"
17569     ],
17570     [
17571         "Guarani",
17572         "Avañe'ẽ",
17573         "gn"
17574     ],
17575     [
17576         "Goan Konkani",
17577         "गोंयची कोंकणी / Gõychi Konknni",
17578         "gom"
17579     ],
17580     [
17581         "Gothic",
17582         "𐌲𐌿𐍄𐌹𐍃𐌺",
17583         "got"
17584     ],
17585     [
17586         "Gujarati",
17587         "ગુજરાતી",
17588         "gu"
17589     ],
17590     [
17591         "Manx",
17592         "Gaelg",
17593         "gv"
17594     ],
17595     [
17596         "Hausa",
17597         "Hausa",
17598         "ha"
17599     ],
17600     [
17601         "Hakka Chinese",
17602         "客家語/Hak-kâ-ngî",
17603         "hak"
17604     ],
17605     [
17606         "Hawaiian",
17607         "Hawaiʻi",
17608         "haw"
17609     ],
17610     [
17611         "Hebrew",
17612         "עברית",
17613         "he"
17614     ],
17615     [
17616         "Hindi",
17617         "हिन्दी",
17618         "hi"
17619     ],
17620     [
17621         "Fiji Hindi",
17622         "Fiji Hindi",
17623         "hif"
17624     ],
17625     [
17626         "Croatian",
17627         "hrvatski",
17628         "hr"
17629     ],
17630     [
17631         "Upper Sorbian",
17632         "hornjoserbsce",
17633         "hsb"
17634     ],
17635     [
17636         "Haitian Creole",
17637         "Kreyòl ayisyen",
17638         "ht"
17639     ],
17640     [
17641         "Hungarian",
17642         "magyar",
17643         "hu"
17644     ],
17645     [
17646         "Armenian",
17647         "Հայերեն",
17648         "hy"
17649     ],
17650     [
17651         "Interlingua",
17652         "interlingua",
17653         "ia"
17654     ],
17655     [
17656         "Indonesian",
17657         "Bahasa Indonesia",
17658         "id"
17659     ],
17660     [
17661         "Interlingue",
17662         "Interlingue",
17663         "ie"
17664     ],
17665     [
17666         "Igbo",
17667         "Igbo",
17668         "ig"
17669     ],
17670     [
17671         "Inupiaq",
17672         "Iñupiak",
17673         "ik"
17674     ],
17675     [
17676         "Iloko",
17677         "Ilokano",
17678         "ilo"
17679     ],
17680     [
17681         "Ido",
17682         "Ido",
17683         "io"
17684     ],
17685     [
17686         "Icelandic",
17687         "íslenska",
17688         "is"
17689     ],
17690     [
17691         "Italian",
17692         "italiano",
17693         "it"
17694     ],
17695     [
17696         "Inuktitut",
17697         "ᐃᓄᒃᑎᑐᑦ/inuktitut",
17698         "iu"
17699     ],
17700     [
17701         "Japanese",
17702         "日本語",
17703         "ja"
17704     ],
17705     [
17706         "Jamaican Creole English",
17707         "Patois",
17708         "jam"
17709     ],
17710     [
17711         "Lojban",
17712         "la .lojban.",
17713         "jbo"
17714     ],
17715     [
17716         "Javanese",
17717         "Basa Jawa",
17718         "jv"
17719     ],
17720     [
17721         "Georgian",
17722         "ქართული",
17723         "ka"
17724     ],
17725     [
17726         "Kara-Kalpak",
17727         "Qaraqalpaqsha",
17728         "kaa"
17729     ],
17730     [
17731         "Kabyle",
17732         "Taqbaylit",
17733         "kab"
17734     ],
17735     [
17736         "Kabardian",
17737         "Адыгэбзэ",
17738         "kbd"
17739     ],
17740     [
17741         "Kongo",
17742         "Kongo",
17743         "kg"
17744     ],
17745     [
17746         "Kikuyu",
17747         "Gĩkũyũ",
17748         "ki"
17749     ],
17750     [
17751         "Kazakh",
17752         "қазақша",
17753         "kk"
17754     ],
17755     [
17756         "Kalaallisut",
17757         "kalaallisut",
17758         "kl"
17759     ],
17760     [
17761         "Khmer",
17762         "ភាសាខ្មែរ",
17763         "km"
17764     ],
17765     [
17766         "Kannada",
17767         "ಕನ್ನಡ",
17768         "kn"
17769     ],
17770     [
17771         "Korean",
17772         "한국어",
17773         "ko"
17774     ],
17775     [
17776         "Komi-Permyak",
17777         "Перем Коми",
17778         "koi"
17779     ],
17780     [
17781         "Karachay-Balkar",
17782         "къарачай-малкъар",
17783         "krc"
17784     ],
17785     [
17786         "Kashmiri",
17787         "कॉशुर / کٲشُر",
17788         "ks"
17789     ],
17790     [
17791         "Colognian",
17792         "Ripoarisch",
17793         "ksh"
17794     ],
17795     [
17796         "Kurdish",
17797         "Kurdî",
17798         "ku"
17799     ],
17800     [
17801         "Komi",
17802         "коми",
17803         "kv"
17804     ],
17805     [
17806         "Cornish",
17807         "kernowek",
17808         "kw"
17809     ],
17810     [
17811         "Kyrgyz",
17812         "Кыргызча",
17813         "ky"
17814     ],
17815     [
17816         "Latin",
17817         "Latina",
17818         "la"
17819     ],
17820     [
17821         "Ladino",
17822         "Ladino",
17823         "lad"
17824     ],
17825     [
17826         "Luxembourgish",
17827         "Lëtzebuergesch",
17828         "lb"
17829     ],
17830     [
17831         "лакку",
17832         "лакку",
17833         "lbe"
17834     ],
17835     [
17836         "Lezghian",
17837         "лезги",
17838         "lez"
17839     ],
17840     [
17841         "Ganda",
17842         "Luganda",
17843         "lg"
17844     ],
17845     [
17846         "Limburgish",
17847         "Limburgs",
17848         "li"
17849     ],
17850     [
17851         "Ligurian",
17852         "Ligure",
17853         "lij"
17854     ],
17855     [
17856         "Lombard",
17857         "lumbaart",
17858         "lmo"
17859     ],
17860     [
17861         "Lingala",
17862         "lingála",
17863         "ln"
17864     ],
17865     [
17866         "Lao",
17867         "ລາວ",
17868         "lo"
17869     ],
17870     [
17871         "Northern Luri",
17872         "لۊری شومالی",
17873         "lrc"
17874     ],
17875     [
17876         "Lithuanian",
17877         "lietuvių",
17878         "lt"
17879     ],
17880     [
17881         "Latgalian",
17882         "latgaļu",
17883         "ltg"
17884     ],
17885     [
17886         "Latvian",
17887         "latviešu",
17888         "lv"
17889     ],
17890     [
17891         "Maithili",
17892         "मैथिली",
17893         "mai"
17894     ],
17895     [
17896         "Basa Banyumasan",
17897         "Basa Banyumasan",
17898         "map-bms"
17899     ],
17900     [
17901         "Moksha",
17902         "мокшень",
17903         "mdf"
17904     ],
17905     [
17906         "Malagasy",
17907         "Malagasy",
17908         "mg"
17909     ],
17910     [
17911         "Eastern Mari",
17912         "олык марий",
17913         "mhr"
17914     ],
17915     [
17916         "Maori",
17917         "Māori",
17918         "mi"
17919     ],
17920     [
17921         "Minangkabau",
17922         "Baso Minangkabau",
17923         "min"
17924     ],
17925     [
17926         "Macedonian",
17927         "македонски",
17928         "mk"
17929     ],
17930     [
17931         "Malayalam",
17932         "മലയാളം",
17933         "ml"
17934     ],
17935     [
17936         "Mongolian",
17937         "монгол",
17938         "mn"
17939     ],
17940     [
17941         "Marathi",
17942         "मराठी",
17943         "mr"
17944     ],
17945     [
17946         "Western Mari",
17947         "кырык мары",
17948         "mrj"
17949     ],
17950     [
17951         "Malay",
17952         "Bahasa Melayu",
17953         "ms"
17954     ],
17955     [
17956         "Maltese",
17957         "Malti",
17958         "mt"
17959     ],
17960     [
17961         "Mirandese",
17962         "Mirandés",
17963         "mwl"
17964     ],
17965     [
17966         "Burmese",
17967         "မြန်မာဘာသာ",
17968         "my"
17969     ],
17970     [
17971         "Erzya",
17972         "эрзянь",
17973         "myv"
17974     ],
17975     [
17976         "Mazanderani",
17977         "مازِرونی",
17978         "mzn"
17979     ],
17980     [
17981         "Nauru",
17982         "Dorerin Naoero",
17983         "na"
17984     ],
17985     [
17986         "Nāhuatl",
17987         "Nāhuatl",
17988         "nah"
17989     ],
17990     [
17991         "Neapolitan",
17992         "Napulitano",
17993         "nap"
17994     ],
17995     [
17996         "Low German",
17997         "Plattdüütsch",
17998         "nds"
17999     ],
18000     [
18001         "Low Saxon",
18002         "Nedersaksies",
18003         "nds-nl"
18004     ],
18005     [
18006         "Nepali",
18007         "नेपाली",
18008         "ne"
18009     ],
18010     [
18011         "Newari",
18012         "नेपाल भाषा",
18013         "new"
18014     ],
18015     [
18016         "Dutch",
18017         "Nederlands",
18018         "nl"
18019     ],
18020     [
18021         "Norwegian Nynorsk",
18022         "norsk nynorsk",
18023         "nn"
18024     ],
18025     [
18026         "Norwegian",
18027         "norsk bokmål",
18028         "no"
18029     ],
18030     [
18031         "Novial",
18032         "Novial",
18033         "nov"
18034     ],
18035     [
18036         "Nouormand",
18037         "Nouormand",
18038         "nrm"
18039     ],
18040     [
18041         "Northern Sotho",
18042         "Sesotho sa Leboa",
18043         "nso"
18044     ],
18045     [
18046         "Navajo",
18047         "Diné bizaad",
18048         "nv"
18049     ],
18050     [
18051         "Nyanja",
18052         "Chi-Chewa",
18053         "ny"
18054     ],
18055     [
18056         "Occitan",
18057         "occitan",
18058         "oc"
18059     ],
18060     [
18061         "Livvi-Karelian",
18062         "Livvinкarjala",
18063         "olo"
18064     ],
18065     [
18066         "Oromo",
18067         "Oromoo",
18068         "om"
18069     ],
18070     [
18071         "Oriya",
18072         "ଓଡ଼ିଆ",
18073         "or"
18074     ],
18075     [
18076         "Ossetic",
18077         "Ирон",
18078         "os"
18079     ],
18080     [
18081         "Punjabi",
18082         "ਪੰਜਾਬੀ",
18083         "pa"
18084     ],
18085     [
18086         "Pangasinan",
18087         "Pangasinan",
18088         "pag"
18089     ],
18090     [
18091         "Pampanga",
18092         "Kapampangan",
18093         "pam"
18094     ],
18095     [
18096         "Papiamento",
18097         "Papiamentu",
18098         "pap"
18099     ],
18100     [
18101         "Picard",
18102         "Picard",
18103         "pcd"
18104     ],
18105     [
18106         "Pennsylvania German",
18107         "Deitsch",
18108         "pdc"
18109     ],
18110     [
18111         "Palatine German",
18112         "Pälzisch",
18113         "pfl"
18114     ],
18115     [
18116         "Pali",
18117         "पालि",
18118         "pi"
18119     ],
18120     [
18121         "Norfuk / Pitkern",
18122         "Norfuk / Pitkern",
18123         "pih"
18124     ],
18125     [
18126         "Polish",
18127         "polski",
18128         "pl"
18129     ],
18130     [
18131         "Piedmontese",
18132         "Piemontèis",
18133         "pms"
18134     ],
18135     [
18136         "Western Punjabi",
18137         "پنجابی",
18138         "pnb"
18139     ],
18140     [
18141         "Pontic",
18142         "Ποντιακά",
18143         "pnt"
18144     ],
18145     [
18146         "Pashto",
18147         "پښتو",
18148         "ps"
18149     ],
18150     [
18151         "Portuguese",
18152         "português",
18153         "pt"
18154     ],
18155     [
18156         "Quechua",
18157         "Runa Simi",
18158         "qu"
18159     ],
18160     [
18161         "Romansh",
18162         "rumantsch",
18163         "rm"
18164     ],
18165     [
18166         "Romani",
18167         "Romani",
18168         "rmy"
18169     ],
18170     [
18171         "Rundi",
18172         "Kirundi",
18173         "rn"
18174     ],
18175     [
18176         "Romanian",
18177         "română",
18178         "ro"
18179     ],
18180     [
18181         "Aromanian",
18182         "armãneashti",
18183         "roa-rup"
18184     ],
18185     [
18186         "tarandíne",
18187         "tarandíne",
18188         "roa-tara"
18189     ],
18190     [
18191         "Russian",
18192         "русский",
18193         "ru"
18194     ],
18195     [
18196         "Rusyn",
18197         "русиньскый",
18198         "rue"
18199     ],
18200     [
18201         "Kinyarwanda",
18202         "Kinyarwanda",
18203         "rw"
18204     ],
18205     [
18206         "Sanskrit",
18207         "संस्कृतम्",
18208         "sa"
18209     ],
18210     [
18211         "Sakha",
18212         "саха тыла",
18213         "sah"
18214     ],
18215     [
18216         "Sardinian",
18217         "sardu",
18218         "sc"
18219     ],
18220     [
18221         "Sicilian",
18222         "sicilianu",
18223         "scn"
18224     ],
18225     [
18226         "Scots",
18227         "Scots",
18228         "sco"
18229     ],
18230     [
18231         "Sindhi",
18232         "سنڌي",
18233         "sd"
18234     ],
18235     [
18236         "Northern Sami",
18237         "sámegiella",
18238         "se"
18239     ],
18240     [
18241         "Sango",
18242         "Sängö",
18243         "sg"
18244     ],
18245     [
18246         "Serbo-Croatian",
18247         "srpskohrvatski / српскохрватски",
18248         "sh"
18249     ],
18250     [
18251         "Sinhala",
18252         "සිංහල",
18253         "si"
18254     ],
18255     [
18256         "Simple English",
18257         "Simple English",
18258         "simple"
18259     ],
18260     [
18261         "Slovak",
18262         "slovenčina",
18263         "sk"
18264     ],
18265     [
18266         "Slovenian",
18267         "slovenščina",
18268         "sl"
18269     ],
18270     [
18271         "Samoan",
18272         "Gagana Samoa",
18273         "sm"
18274     ],
18275     [
18276         "Shona",
18277         "chiShona",
18278         "sn"
18279     ],
18280     [
18281         "Somali",
18282         "Soomaaliga",
18283         "so"
18284     ],
18285     [
18286         "Albanian",
18287         "shqip",
18288         "sq"
18289     ],
18290     [
18291         "Serbian",
18292         "српски / srpski",
18293         "sr"
18294     ],
18295     [
18296         "Sranan Tongo",
18297         "Sranantongo",
18298         "srn"
18299     ],
18300     [
18301         "Swati",
18302         "SiSwati",
18303         "ss"
18304     ],
18305     [
18306         "Southern Sotho",
18307         "Sesotho",
18308         "st"
18309     ],
18310     [
18311         "Saterland Frisian",
18312         "Seeltersk",
18313         "stq"
18314     ],
18315     [
18316         "Sundanese",
18317         "Basa Sunda",
18318         "su"
18319     ],
18320     [
18321         "Swedish",
18322         "svenska",
18323         "sv"
18324     ],
18325     [
18326         "Swahili",
18327         "Kiswahili",
18328         "sw"
18329     ],
18330     [
18331         "Silesian",
18332         "ślůnski",
18333         "szl"
18334     ],
18335     [
18336         "Tamil",
18337         "தமிழ்",
18338         "ta"
18339     ],
18340     [
18341         "Tulu",
18342         "ತುಳು",
18343         "tcy"
18344     ],
18345     [
18346         "Telugu",
18347         "తెలుగు",
18348         "te"
18349     ],
18350     [
18351         "Tetum",
18352         "tetun",
18353         "tet"
18354     ],
18355     [
18356         "Tajik",
18357         "тоҷикӣ",
18358         "tg"
18359     ],
18360     [
18361         "Thai",
18362         "ไทย",
18363         "th"
18364     ],
18365     [
18366         "Tigrinya",
18367         "ትግርኛ",
18368         "ti"
18369     ],
18370     [
18371         "Turkmen",
18372         "Türkmençe",
18373         "tk"
18374     ],
18375     [
18376         "Tagalog",
18377         "Tagalog",
18378         "tl"
18379     ],
18380     [
18381         "Tswana",
18382         "Setswana",
18383         "tn"
18384     ],
18385     [
18386         "Tongan",
18387         "lea faka-Tonga",
18388         "to"
18389     ],
18390     [
18391         "Tok Pisin",
18392         "Tok Pisin",
18393         "tpi"
18394     ],
18395     [
18396         "Turkish",
18397         "Türkçe",
18398         "tr"
18399     ],
18400     [
18401         "Tsonga",
18402         "Xitsonga",
18403         "ts"
18404     ],
18405     [
18406         "Tatar",
18407         "татарча/tatarça",
18408         "tt"
18409     ],
18410     [
18411         "Tumbuka",
18412         "chiTumbuka",
18413         "tum"
18414     ],
18415     [
18416         "Twi",
18417         "Twi",
18418         "tw"
18419     ],
18420     [
18421         "Tahitian",
18422         "reo tahiti",
18423         "ty"
18424     ],
18425     [
18426         "Tuvinian",
18427         "тыва дыл",
18428         "tyv"
18429     ],
18430     [
18431         "Udmurt",
18432         "удмурт",
18433         "udm"
18434     ],
18435     [
18436         "Uyghur",
18437         "ئۇيغۇرچە / Uyghurche",
18438         "ug"
18439     ],
18440     [
18441         "Ukrainian",
18442         "українська",
18443         "uk"
18444     ],
18445     [
18446         "Urdu",
18447         "اردو",
18448         "ur"
18449     ],
18450     [
18451         "Uzbek",
18452         "oʻzbekcha/ўзбекча",
18453         "uz"
18454     ],
18455     [
18456         "Venda",
18457         "Tshivenda",
18458         "ve"
18459     ],
18460     [
18461         "Venetian",
18462         "vèneto",
18463         "vec"
18464     ],
18465     [
18466         "Veps",
18467         "vepsän kel’",
18468         "vep"
18469     ],
18470     [
18471         "Vietnamese",
18472         "Tiếng Việt",
18473         "vi"
18474     ],
18475     [
18476         "West Flemish",
18477         "West-Vlams",
18478         "vls"
18479     ],
18480     [
18481         "Volapük",
18482         "Volapük",
18483         "vo"
18484     ],
18485     [
18486         "Walloon",
18487         "walon",
18488         "wa"
18489     ],
18490     [
18491         "Waray",
18492         "Winaray",
18493         "war"
18494     ],
18495     [
18496         "Wolof",
18497         "Wolof",
18498         "wo"
18499     ],
18500     [
18501         "Wu Chinese",
18502         "吴语",
18503         "wuu"
18504     ],
18505     [
18506         "Kalmyk",
18507         "хальмг",
18508         "xal"
18509     ],
18510     [
18511         "Xhosa",
18512         "isiXhosa",
18513         "xh"
18514     ],
18515     [
18516         "Mingrelian",
18517         "მარგალური",
18518         "xmf"
18519     ],
18520     [
18521         "Yiddish",
18522         "ייִדיש",
18523         "yi"
18524     ],
18525     [
18526         "Yoruba",
18527         "Yorùbá",
18528         "yo"
18529     ],
18530     [
18531         "Zhuang",
18532         "Vahcuengh",
18533         "za"
18534     ],
18535     [
18536         "Zeelandic",
18537         "Zeêuws",
18538         "zea"
18539     ],
18540     [
18541         "Chinese",
18542         "中文",
18543         "zh"
18544     ],
18545     [
18546         "Classical Chinese",
18547         "文言",
18548         "zh-classical"
18549     ],
18550     [
18551         "Chinese (Min Nan)",
18552         "Bân-lâm-gú",
18553         "zh-min-nan"
18554     ],
18555     [
18556         "Cantonese",
18557         "粵語",
18558         "zh-yue"
18559     ],
18560     [
18561         "Zulu",
18562         "isiZulu",
18563         "zu"
18564     ]
18565 ];
18566
18567 var dataFeatureIcons =  {
18568         "circle-stroked-24": {"x":0,"y":0,"width":24,"height":24},
18569         "circle-stroked-18": {"x":24,"y":0,"width":18,"height":18},
18570         "circle-stroked-12": {"x":42,"y":0,"width":12,"height":12},
18571         "circle-24": {"x":54,"y":0,"width":24,"height":24},
18572         "circle-18": {"x":78,"y":0,"width":18,"height":18},
18573         "circle-12": {"x":96,"y":0,"width":12,"height":12},
18574         "square-stroked-24": {"x":108,"y":0,"width":24,"height":24},
18575         "square-stroked-18": {"x":132,"y":0,"width":18,"height":18},
18576         "square-stroked-12": {"x":150,"y":0,"width":12,"height":12},
18577         "square-24": {"x":162,"y":0,"width":24,"height":24},
18578         "square-18": {"x":186,"y":0,"width":18,"height":18},
18579         "square-12": {"x":204,"y":0,"width":12,"height":12},
18580         "triangle-stroked-24": {"x":216,"y":0,"width":24,"height":24},
18581         "triangle-stroked-18": {"x":240,"y":0,"width":18,"height":18},
18582         "triangle-stroked-12": {"x":258,"y":0,"width":12,"height":12},
18583         "triangle-24": {"x":0,"y":24,"width":24,"height":24},
18584         "triangle-18": {"x":24,"y":24,"width":18,"height":18},
18585         "triangle-12": {"x":42,"y":24,"width":12,"height":12},
18586         "star-stroked-24": {"x":54,"y":24,"width":24,"height":24},
18587         "star-stroked-18": {"x":78,"y":24,"width":18,"height":18},
18588         "star-stroked-12": {"x":96,"y":24,"width":12,"height":12},
18589         "star-24": {"x":108,"y":24,"width":24,"height":24},
18590         "star-18": {"x":132,"y":24,"width":18,"height":18},
18591         "star-12": {"x":150,"y":24,"width":12,"height":12},
18592         "cross-24": {"x":162,"y":24,"width":24,"height":24},
18593         "cross-18": {"x":186,"y":24,"width":18,"height":18},
18594         "cross-12": {"x":204,"y":24,"width":12,"height":12},
18595         "marker-stroked-24": {"x":216,"y":24,"width":24,"height":24},
18596         "marker-stroked-18": {"x":240,"y":24,"width":18,"height":18},
18597         "marker-stroked-12": {"x":258,"y":24,"width":12,"height":12},
18598         "marker-24": {"x":0,"y":48,"width":24,"height":24},
18599         "marker-18": {"x":24,"y":48,"width":18,"height":18},
18600         "marker-12": {"x":42,"y":48,"width":12,"height":12},
18601         "religious-jewish-24": {"x":54,"y":48,"width":24,"height":24},
18602         "religious-jewish-18": {"x":78,"y":48,"width":18,"height":18},
18603         "religious-jewish-12": {"x":96,"y":48,"width":12,"height":12},
18604         "religious-christian-24": {"x":108,"y":48,"width":24,"height":24},
18605         "religious-christian-18": {"x":132,"y":48,"width":18,"height":18},
18606         "religious-christian-12": {"x":150,"y":48,"width":12,"height":12},
18607         "religious-muslim-24": {"x":162,"y":48,"width":24,"height":24},
18608         "religious-muslim-18": {"x":186,"y":48,"width":18,"height":18},
18609         "religious-muslim-12": {"x":204,"y":48,"width":12,"height":12},
18610         "cemetery-24": {"x":216,"y":48,"width":24,"height":24},
18611         "cemetery-18": {"x":240,"y":48,"width":18,"height":18},
18612         "cemetery-12": {"x":258,"y":48,"width":12,"height":12},
18613         "rocket-24": {"x":0,"y":72,"width":24,"height":24},
18614         "rocket-18": {"x":24,"y":72,"width":18,"height":18},
18615         "rocket-12": {"x":42,"y":72,"width":12,"height":12},
18616         "airport-24": {"x":54,"y":72,"width":24,"height":24},
18617         "airport-18": {"x":78,"y":72,"width":18,"height":18},
18618         "airport-12": {"x":96,"y":72,"width":12,"height":12},
18619         "heliport-24": {"x":108,"y":72,"width":24,"height":24},
18620         "heliport-18": {"x":132,"y":72,"width":18,"height":18},
18621         "heliport-12": {"x":150,"y":72,"width":12,"height":12},
18622         "rail-24": {"x":162,"y":72,"width":24,"height":24},
18623         "rail-18": {"x":186,"y":72,"width":18,"height":18},
18624         "rail-12": {"x":204,"y":72,"width":12,"height":12},
18625         "rail-metro-24": {"x":216,"y":72,"width":24,"height":24},
18626         "rail-metro-18": {"x":240,"y":72,"width":18,"height":18},
18627         "rail-metro-12": {"x":258,"y":72,"width":12,"height":12},
18628         "rail-light-24": {"x":0,"y":96,"width":24,"height":24},
18629         "rail-light-18": {"x":24,"y":96,"width":18,"height":18},
18630         "rail-light-12": {"x":42,"y":96,"width":12,"height":12},
18631         "bus-24": {"x":54,"y":96,"width":24,"height":24},
18632         "bus-18": {"x":78,"y":96,"width":18,"height":18},
18633         "bus-12": {"x":96,"y":96,"width":12,"height":12},
18634         "fuel-24": {"x":108,"y":96,"width":24,"height":24},
18635         "fuel-18": {"x":132,"y":96,"width":18,"height":18},
18636         "fuel-12": {"x":150,"y":96,"width":12,"height":12},
18637         "parking-24": {"x":162,"y":96,"width":24,"height":24},
18638         "parking-18": {"x":186,"y":96,"width":18,"height":18},
18639         "parking-12": {"x":204,"y":96,"width":12,"height":12},
18640         "parking-garage-24": {"x":216,"y":96,"width":24,"height":24},
18641         "parking-garage-18": {"x":240,"y":96,"width":18,"height":18},
18642         "parking-garage-12": {"x":258,"y":96,"width":12,"height":12},
18643         "airfield-24": {"x":0,"y":120,"width":24,"height":24},
18644         "airfield-18": {"x":24,"y":120,"width":18,"height":18},
18645         "airfield-12": {"x":42,"y":120,"width":12,"height":12},
18646         "roadblock-24": {"x":54,"y":120,"width":24,"height":24},
18647         "roadblock-18": {"x":78,"y":120,"width":18,"height":18},
18648         "roadblock-12": {"x":96,"y":120,"width":12,"height":12},
18649         "ferry-24": {"x":108,"y":120,"width":24,"height":24},
18650         "ferry-18": {"x":132,"y":120,"width":18,"height":18},
18651         "ferry-12": {"x":150,"y":120,"width":12,"height":12},
18652         "harbor-24": {"x":162,"y":120,"width":24,"height":24},
18653         "harbor-18": {"x":186,"y":120,"width":18,"height":18},
18654         "harbor-12": {"x":204,"y":120,"width":12,"height":12},
18655         "bicycle-24": {"x":216,"y":120,"width":24,"height":24},
18656         "bicycle-18": {"x":240,"y":120,"width":18,"height":18},
18657         "bicycle-12": {"x":258,"y":120,"width":12,"height":12},
18658         "park-24": {"x":0,"y":144,"width":24,"height":24},
18659         "park-18": {"x":24,"y":144,"width":18,"height":18},
18660         "park-12": {"x":42,"y":144,"width":12,"height":12},
18661         "park2-24": {"x":54,"y":144,"width":24,"height":24},
18662         "park2-18": {"x":78,"y":144,"width":18,"height":18},
18663         "park2-12": {"x":96,"y":144,"width":12,"height":12},
18664         "museum-24": {"x":108,"y":144,"width":24,"height":24},
18665         "museum-18": {"x":132,"y":144,"width":18,"height":18},
18666         "museum-12": {"x":150,"y":144,"width":12,"height":12},
18667         "lodging-24": {"x":162,"y":144,"width":24,"height":24},
18668         "lodging-18": {"x":186,"y":144,"width":18,"height":18},
18669         "lodging-12": {"x":204,"y":144,"width":12,"height":12},
18670         "monument-24": {"x":216,"y":144,"width":24,"height":24},
18671         "monument-18": {"x":240,"y":144,"width":18,"height":18},
18672         "monument-12": {"x":258,"y":144,"width":12,"height":12},
18673         "zoo-24": {"x":0,"y":168,"width":24,"height":24},
18674         "zoo-18": {"x":24,"y":168,"width":18,"height":18},
18675         "zoo-12": {"x":42,"y":168,"width":12,"height":12},
18676         "garden-24": {"x":54,"y":168,"width":24,"height":24},
18677         "garden-18": {"x":78,"y":168,"width":18,"height":18},
18678         "garden-12": {"x":96,"y":168,"width":12,"height":12},
18679         "campsite-24": {"x":108,"y":168,"width":24,"height":24},
18680         "campsite-18": {"x":132,"y":168,"width":18,"height":18},
18681         "campsite-12": {"x":150,"y":168,"width":12,"height":12},
18682         "theatre-24": {"x":162,"y":168,"width":24,"height":24},
18683         "theatre-18": {"x":186,"y":168,"width":18,"height":18},
18684         "theatre-12": {"x":204,"y":168,"width":12,"height":12},
18685         "art-gallery-24": {"x":216,"y":168,"width":24,"height":24},
18686         "art-gallery-18": {"x":240,"y":168,"width":18,"height":18},
18687         "art-gallery-12": {"x":258,"y":168,"width":12,"height":12},
18688         "pitch-24": {"x":0,"y":192,"width":24,"height":24},
18689         "pitch-18": {"x":24,"y":192,"width":18,"height":18},
18690         "pitch-12": {"x":42,"y":192,"width":12,"height":12},
18691         "soccer-24": {"x":54,"y":192,"width":24,"height":24},
18692         "soccer-18": {"x":78,"y":192,"width":18,"height":18},
18693         "soccer-12": {"x":96,"y":192,"width":12,"height":12},
18694         "america-football-24": {"x":108,"y":192,"width":24,"height":24},
18695         "america-football-18": {"x":132,"y":192,"width":18,"height":18},
18696         "america-football-12": {"x":150,"y":192,"width":12,"height":12},
18697         "tennis-24": {"x":162,"y":192,"width":24,"height":24},
18698         "tennis-18": {"x":186,"y":192,"width":18,"height":18},
18699         "tennis-12": {"x":204,"y":192,"width":12,"height":12},
18700         "basketball-24": {"x":216,"y":192,"width":24,"height":24},
18701         "basketball-18": {"x":240,"y":192,"width":18,"height":18},
18702         "basketball-12": {"x":258,"y":192,"width":12,"height":12},
18703         "baseball-24": {"x":0,"y":216,"width":24,"height":24},
18704         "baseball-18": {"x":24,"y":216,"width":18,"height":18},
18705         "baseball-12": {"x":42,"y":216,"width":12,"height":12},
18706         "golf-24": {"x":54,"y":216,"width":24,"height":24},
18707         "golf-18": {"x":78,"y":216,"width":18,"height":18},
18708         "golf-12": {"x":96,"y":216,"width":12,"height":12},
18709         "swimming-24": {"x":108,"y":216,"width":24,"height":24},
18710         "swimming-18": {"x":132,"y":216,"width":18,"height":18},
18711         "swimming-12": {"x":150,"y":216,"width":12,"height":12},
18712         "cricket-24": {"x":162,"y":216,"width":24,"height":24},
18713         "cricket-18": {"x":186,"y":216,"width":18,"height":18},
18714         "cricket-12": {"x":204,"y":216,"width":12,"height":12},
18715         "skiing-24": {"x":216,"y":216,"width":24,"height":24},
18716         "skiing-18": {"x":240,"y":216,"width":18,"height":18},
18717         "skiing-12": {"x":258,"y":216,"width":12,"height":12},
18718         "school-24": {"x":0,"y":240,"width":24,"height":24},
18719         "school-18": {"x":24,"y":240,"width":18,"height":18},
18720         "school-12": {"x":42,"y":240,"width":12,"height":12},
18721         "college-24": {"x":54,"y":240,"width":24,"height":24},
18722         "college-18": {"x":78,"y":240,"width":18,"height":18},
18723         "college-12": {"x":96,"y":240,"width":12,"height":12},
18724         "library-24": {"x":108,"y":240,"width":24,"height":24},
18725         "library-18": {"x":132,"y":240,"width":18,"height":18},
18726         "library-12": {"x":150,"y":240,"width":12,"height":12},
18727         "post-24": {"x":162,"y":240,"width":24,"height":24},
18728         "post-18": {"x":186,"y":240,"width":18,"height":18},
18729         "post-12": {"x":204,"y":240,"width":12,"height":12},
18730         "fire-station-24": {"x":216,"y":240,"width":24,"height":24},
18731         "fire-station-18": {"x":240,"y":240,"width":18,"height":18},
18732         "fire-station-12": {"x":258,"y":240,"width":12,"height":12},
18733         "town-hall-24": {"x":0,"y":264,"width":24,"height":24},
18734         "town-hall-18": {"x":24,"y":264,"width":18,"height":18},
18735         "town-hall-12": {"x":42,"y":264,"width":12,"height":12},
18736         "police-24": {"x":54,"y":264,"width":24,"height":24},
18737         "police-18": {"x":78,"y":264,"width":18,"height":18},
18738         "police-12": {"x":96,"y":264,"width":12,"height":12},
18739         "prison-24": {"x":108,"y":264,"width":24,"height":24},
18740         "prison-18": {"x":132,"y":264,"width":18,"height":18},
18741         "prison-12": {"x":150,"y":264,"width":12,"height":12},
18742         "embassy-24": {"x":162,"y":264,"width":24,"height":24},
18743         "embassy-18": {"x":186,"y":264,"width":18,"height":18},
18744         "embassy-12": {"x":204,"y":264,"width":12,"height":12},
18745         "beer-24": {"x":216,"y":264,"width":24,"height":24},
18746         "beer-18": {"x":240,"y":264,"width":18,"height":18},
18747         "beer-12": {"x":258,"y":264,"width":12,"height":12},
18748         "restaurant-24": {"x":0,"y":288,"width":24,"height":24},
18749         "restaurant-18": {"x":24,"y":288,"width":18,"height":18},
18750         "restaurant-12": {"x":42,"y":288,"width":12,"height":12},
18751         "cafe-24": {"x":54,"y":288,"width":24,"height":24},
18752         "cafe-18": {"x":78,"y":288,"width":18,"height":18},
18753         "cafe-12": {"x":96,"y":288,"width":12,"height":12},
18754         "shop-24": {"x":108,"y":288,"width":24,"height":24},
18755         "shop-18": {"x":132,"y":288,"width":18,"height":18},
18756         "shop-12": {"x":150,"y":288,"width":12,"height":12},
18757         "fast-food-24": {"x":162,"y":288,"width":24,"height":24},
18758         "fast-food-18": {"x":186,"y":288,"width":18,"height":18},
18759         "fast-food-12": {"x":204,"y":288,"width":12,"height":12},
18760         "bar-24": {"x":216,"y":288,"width":24,"height":24},
18761         "bar-18": {"x":240,"y":288,"width":18,"height":18},
18762         "bar-12": {"x":258,"y":288,"width":12,"height":12},
18763         "bank-24": {"x":0,"y":312,"width":24,"height":24},
18764         "bank-18": {"x":24,"y":312,"width":18,"height":18},
18765         "bank-12": {"x":42,"y":312,"width":12,"height":12},
18766         "grocery-24": {"x":54,"y":312,"width":24,"height":24},
18767         "grocery-18": {"x":78,"y":312,"width":18,"height":18},
18768         "grocery-12": {"x":96,"y":312,"width":12,"height":12},
18769         "cinema-24": {"x":108,"y":312,"width":24,"height":24},
18770         "cinema-18": {"x":132,"y":312,"width":18,"height":18},
18771         "cinema-12": {"x":150,"y":312,"width":12,"height":12},
18772         "pharmacy-24": {"x":162,"y":312,"width":24,"height":24},
18773         "pharmacy-18": {"x":186,"y":312,"width":18,"height":18},
18774         "pharmacy-12": {"x":204,"y":312,"width":12,"height":12},
18775         "hospital-24": {"x":216,"y":312,"width":24,"height":24},
18776         "hospital-18": {"x":240,"y":312,"width":18,"height":18},
18777         "hospital-12": {"x":258,"y":312,"width":12,"height":12},
18778         "danger-24": {"x":0,"y":336,"width":24,"height":24},
18779         "danger-18": {"x":24,"y":336,"width":18,"height":18},
18780         "danger-12": {"x":42,"y":336,"width":12,"height":12},
18781         "industrial-24": {"x":54,"y":336,"width":24,"height":24},
18782         "industrial-18": {"x":78,"y":336,"width":18,"height":18},
18783         "industrial-12": {"x":96,"y":336,"width":12,"height":12},
18784         "warehouse-24": {"x":108,"y":336,"width":24,"height":24},
18785         "warehouse-18": {"x":132,"y":336,"width":18,"height":18},
18786         "warehouse-12": {"x":150,"y":336,"width":12,"height":12},
18787         "commercial-24": {"x":162,"y":336,"width":24,"height":24},
18788         "commercial-18": {"x":186,"y":336,"width":18,"height":18},
18789         "commercial-12": {"x":204,"y":336,"width":12,"height":12},
18790         "building-24": {"x":216,"y":336,"width":24,"height":24},
18791         "building-18": {"x":240,"y":336,"width":18,"height":18},
18792         "building-12": {"x":258,"y":336,"width":12,"height":12},
18793         "place-of-worship-24": {"x":0,"y":360,"width":24,"height":24},
18794         "place-of-worship-18": {"x":24,"y":360,"width":18,"height":18},
18795         "place-of-worship-12": {"x":42,"y":360,"width":12,"height":12},
18796         "alcohol-shop-24": {"x":54,"y":360,"width":24,"height":24},
18797         "alcohol-shop-18": {"x":78,"y":360,"width":18,"height":18},
18798         "alcohol-shop-12": {"x":96,"y":360,"width":12,"height":12},
18799         "logging-24": {"x":108,"y":360,"width":24,"height":24},
18800         "logging-18": {"x":132,"y":360,"width":18,"height":18},
18801         "logging-12": {"x":150,"y":360,"width":12,"height":12},
18802         "oil-well-24": {"x":162,"y":360,"width":24,"height":24},
18803         "oil-well-18": {"x":186,"y":360,"width":18,"height":18},
18804         "oil-well-12": {"x":204,"y":360,"width":12,"height":12},
18805         "slaughterhouse-24": {"x":216,"y":360,"width":24,"height":24},
18806         "slaughterhouse-18": {"x":240,"y":360,"width":18,"height":18},
18807         "slaughterhouse-12": {"x":258,"y":360,"width":12,"height":12},
18808         "dam-24": {"x":0,"y":384,"width":24,"height":24},
18809         "dam-18": {"x":24,"y":384,"width":18,"height":18},
18810         "dam-12": {"x":42,"y":384,"width":12,"height":12},
18811         "water-24": {"x":54,"y":384,"width":24,"height":24},
18812         "water-18": {"x":78,"y":384,"width":18,"height":18},
18813         "water-12": {"x":96,"y":384,"width":12,"height":12},
18814         "wetland-24": {"x":108,"y":384,"width":24,"height":24},
18815         "wetland-18": {"x":132,"y":384,"width":18,"height":18},
18816         "wetland-12": {"x":150,"y":384,"width":12,"height":12},
18817         "disability-24": {"x":162,"y":384,"width":24,"height":24},
18818         "disability-18": {"x":186,"y":384,"width":18,"height":18},
18819         "disability-12": {"x":204,"y":384,"width":12,"height":12},
18820         "telephone-24": {"x":216,"y":384,"width":24,"height":24},
18821         "telephone-18": {"x":240,"y":384,"width":18,"height":18},
18822         "telephone-12": {"x":258,"y":384,"width":12,"height":12},
18823         "emergency-telephone-24": {"x":0,"y":408,"width":24,"height":24},
18824         "emergency-telephone-18": {"x":24,"y":408,"width":18,"height":18},
18825         "emergency-telephone-12": {"x":42,"y":408,"width":12,"height":12},
18826         "toilets-24": {"x":54,"y":408,"width":24,"height":24},
18827         "toilets-18": {"x":78,"y":408,"width":18,"height":18},
18828         "toilets-12": {"x":96,"y":408,"width":12,"height":12},
18829         "waste-basket-24": {"x":108,"y":408,"width":24,"height":24},
18830         "waste-basket-18": {"x":132,"y":408,"width":18,"height":18},
18831         "waste-basket-12": {"x":150,"y":408,"width":12,"height":12},
18832         "music-24": {"x":162,"y":408,"width":24,"height":24},
18833         "music-18": {"x":186,"y":408,"width":18,"height":18},
18834         "music-12": {"x":204,"y":408,"width":12,"height":12},
18835         "land-use-24": {"x":216,"y":408,"width":24,"height":24},
18836         "land-use-18": {"x":240,"y":408,"width":18,"height":18},
18837         "land-use-12": {"x":258,"y":408,"width":12,"height":12},
18838         "city-24": {"x":0,"y":432,"width":24,"height":24},
18839         "city-18": {"x":24,"y":432,"width":18,"height":18},
18840         "city-12": {"x":42,"y":432,"width":12,"height":12},
18841         "town-24": {"x":54,"y":432,"width":24,"height":24},
18842         "town-18": {"x":78,"y":432,"width":18,"height":18},
18843         "town-12": {"x":96,"y":432,"width":12,"height":12},
18844         "village-24": {"x":108,"y":432,"width":24,"height":24},
18845         "village-18": {"x":132,"y":432,"width":18,"height":18},
18846         "village-12": {"x":150,"y":432,"width":12,"height":12},
18847         "farm-24": {"x":162,"y":432,"width":24,"height":24},
18848         "farm-18": {"x":186,"y":432,"width":18,"height":18},
18849         "farm-12": {"x":204,"y":432,"width":12,"height":12},
18850         "bakery-24": {"x":216,"y":432,"width":24,"height":24},
18851         "bakery-18": {"x":240,"y":432,"width":18,"height":18},
18852         "bakery-12": {"x":258,"y":432,"width":12,"height":12},
18853         "dog-park-24": {"x":0,"y":456,"width":24,"height":24},
18854         "dog-park-18": {"x":24,"y":456,"width":18,"height":18},
18855         "dog-park-12": {"x":42,"y":456,"width":12,"height":12},
18856         "lighthouse-24": {"x":54,"y":456,"width":24,"height":24},
18857         "lighthouse-18": {"x":78,"y":456,"width":18,"height":18},
18858         "lighthouse-12": {"x":96,"y":456,"width":12,"height":12},
18859         "clothing-store-24": {"x":108,"y":456,"width":24,"height":24},
18860         "clothing-store-18": {"x":132,"y":456,"width":18,"height":18},
18861         "clothing-store-12": {"x":150,"y":456,"width":12,"height":12},
18862         "polling-place-24": {"x":162,"y":456,"width":24,"height":24},
18863         "polling-place-18": {"x":186,"y":456,"width":18,"height":18},
18864         "polling-place-12": {"x":204,"y":456,"width":12,"height":12},
18865         "playground-24": {"x":216,"y":456,"width":24,"height":24},
18866         "playground-18": {"x":240,"y":456,"width":18,"height":18},
18867         "playground-12": {"x":258,"y":456,"width":12,"height":12},
18868         "entrance-24": {"x":0,"y":480,"width":24,"height":24},
18869         "entrance-18": {"x":24,"y":480,"width":18,"height":18},
18870         "entrance-12": {"x":42,"y":480,"width":12,"height":12},
18871         "heart-24": {"x":54,"y":480,"width":24,"height":24},
18872         "heart-18": {"x":78,"y":480,"width":18,"height":18},
18873         "heart-12": {"x":96,"y":480,"width":12,"height":12},
18874         "london-underground-24": {"x":108,"y":480,"width":24,"height":24},
18875         "london-underground-18": {"x":132,"y":480,"width":18,"height":18},
18876         "london-underground-12": {"x":150,"y":480,"width":12,"height":12},
18877         "minefield-24": {"x":162,"y":480,"width":24,"height":24},
18878         "minefield-18": {"x":186,"y":480,"width":18,"height":18},
18879         "minefield-12": {"x":204,"y":480,"width":12,"height":12},
18880         "rail-underground-24": {"x":216,"y":480,"width":24,"height":24},
18881         "rail-underground-18": {"x":240,"y":480,"width":18,"height":18},
18882         "rail-underground-12": {"x":258,"y":480,"width":12,"height":12},
18883         "rail-above-24": {"x":0,"y":504,"width":24,"height":24},
18884         "rail-above-18": {"x":24,"y":504,"width":18,"height":18},
18885         "rail-above-12": {"x":42,"y":504,"width":12,"height":12},
18886         "camera-24": {"x":54,"y":504,"width":24,"height":24},
18887         "camera-18": {"x":78,"y":504,"width":18,"height":18},
18888         "camera-12": {"x":96,"y":504,"width":12,"height":12},
18889         "laundry-24": {"x":108,"y":504,"width":24,"height":24},
18890         "laundry-18": {"x":132,"y":504,"width":18,"height":18},
18891         "laundry-12": {"x":150,"y":504,"width":12,"height":12},
18892         "car-24": {"x":162,"y":504,"width":24,"height":24},
18893         "car-18": {"x":186,"y":504,"width":18,"height":18},
18894         "car-12": {"x":204,"y":504,"width":12,"height":12},
18895         "suitcase-24": {"x":216,"y":504,"width":24,"height":24},
18896         "suitcase-18": {"x":240,"y":504,"width":18,"height":18},
18897         "suitcase-12": {"x":258,"y":504,"width":12,"height":12},
18898         "hairdresser-24": {"x":0,"y":528,"width":24,"height":24},
18899         "hairdresser-18": {"x":24,"y":528,"width":18,"height":18},
18900         "hairdresser-12": {"x":42,"y":528,"width":12,"height":12},
18901         "chemist-24": {"x":54,"y":528,"width":24,"height":24},
18902         "chemist-18": {"x":78,"y":528,"width":18,"height":18},
18903         "chemist-12": {"x":96,"y":528,"width":12,"height":12},
18904         "mobilephone-24": {"x":108,"y":528,"width":24,"height":24},
18905         "mobilephone-18": {"x":132,"y":528,"width":18,"height":18},
18906         "mobilephone-12": {"x":150,"y":528,"width":12,"height":12},
18907         "scooter-24": {"x":162,"y":528,"width":24,"height":24},
18908         "scooter-18": {"x":186,"y":528,"width":18,"height":18},
18909         "scooter-12": {"x":204,"y":528,"width":12,"height":12},
18910         "gift-24": {"x":216,"y":528,"width":24,"height":24},
18911         "gift-18": {"x":240,"y":528,"width":18,"height":18},
18912         "gift-12": {"x":258,"y":528,"width":12,"height":12},
18913         "ice-cream-24": {"x":0,"y":552,"width":24,"height":24},
18914         "ice-cream-18": {"x":24,"y":552,"width":18,"height":18},
18915         "ice-cream-12": {"x":42,"y":552,"width":12,"height":12}
18916 };
18917
18918 var amenity = {"fuel":{"76":{"count":314},"Neste":{"count":189},"BP":{"count":2511},"Shell":{"count":8380},"Agip":{"count":2651},"Migrol":{"count":65},"Avia":{"count":897},"Texaco":{"count":680},"Total":{"count":2607},"Statoil":{"count":596},"Esso":{"count":3652},"Jet":{"count":441},"Avanti":{"count":90},"Sainsbury's":{"count":58},"OMV":{"count":701},"Aral":{"count":1339},"Tesco":{"count":197},"JET":{"count":180},"Morrisons":{"count":111},"United":{"count":91},"Canadian Tire":{"count":66},"Mobil":{"count":613},"Caltex":{"count":1001},"Sunoco":{"count":355},"Q8":{"count":1161},"ABC":{"count":79},"ARAL":{"count":375},"CEPSA":{"count":1018},"BFT":{"count":89},"Petron":{"count":878},"Intermarché":{"count":434},"Total Access":{"count":51},"Super U":{"count":124},"Auchan":{"count":53},"Elf":{"count":129},"Carrefour":{"count":205},"Station Service E. Leclerc":{"count":530},"Shell Express":{"count":131},"Hess":{"count":127},"Flying V":{"count":129},"bft":{"count":168},"Gulf":{"count":199},"PTT":{"count":191},"St1":{"count":100},"Teboil":{"count":115},"HEM":{"count":212},"GALP":{"count":626},"OK":{"count":163},"ÖMV":{"count":101},"Tinq":{"count":215},"OKQ8":{"count":186},"Repsol":{"count":424},"Westfalen":{"count":96},"Esso Express":{"count":98},"Raiffeisenbank":{"count":117},"Tamoil":{"count":866},"Engen":{"count":241},"Sasol":{"count":59},"Topaz":{"count":78},"LPG":{"count":174},"Coop":{"count":62},"Orlen":{"count":598},"Oilibya":{"count":68},"Tango":{"count":122},"Star":{"count":319},"Петрол":{"count":84},"Cepsa":{"count":96},"OIL!":{"count":63},"Ultramar":{"count":125},"Irving":{"count":87},"Lukoil":{"count":701},"Petro-Canada":{"count":489},"7-Eleven":{"count":488},"Agrola":{"count":69},"Husky":{"count":126},"Slovnaft":{"count":219},"Sheetz":{"count":134},"Mol":{"count":61},"Petronas":{"count":159},"Газпромнефть":{"count":748},"Лукойл":{"count":1477},"Elan":{"count":112},"Роснефть":{"count":638},"Turmöl":{"count":57},"Neste A24":{"count":55},"Marathon":{"count":189},"Valero":{"count":366},"Eni":{"count":236},"Chevron":{"count":954},"ТНК":{"count":520},"REPSOL":{"count":1603},"MOL":{"count":228},"Bliska":{"count":150},"Api":{"count":302},"Arco":{"count":179},"Pemex":{"count":423},"Exxon":{"count":506},"Coles Express":{"count":115},"Petrom":{"count":259},"PETRONOR":{"count":207},"Rompetrol":{"count":174},"Lotos":{"count":178},"ОМВ":{"count":60},"BR":{"count":129},"Copec":{"count":505},"Petrobras":{"count":270},"Liberty":{"count":55},"IP":{"count":871},"Erg":{"count":596},"Eneos":{"count":97},"Citgo":{"count":279},"Metano":{"count":208},"Сургутнефтегаз":{"count":61},"EKO":{"count":59},"Eko":{"count":58},"Indipend.":{"count":172},"IES":{"count":63},"TotalErg":{"count":89},"Cenex":{"count":115},"ПТК":{"count":82},"HP":{"count":79},"Phillips 66":{"count":216},"CARREFOUR":{"count":74},"ERG":{"count":76},"Speedway":{"count":148},"Benzina":{"count":96},"Татнефть":{"count":264},"Terpel":{"count":259},"WOG":{"count":189},"Seaoil":{"count":54},"АЗС":{"count":1077},"Kwik Trip":{"count":108},"Wawa":{"count":89},"Pertamina":{"count":186},"COSMO":{"count":64},"Z":{"count":76},"Indian Oil":{"count":183},"АГЗС":{"count":494},"INA":{"count":121},"JOMO":{"count":62},"Holiday":{"count":97},"YPF":{"count":70},"IDEMITSU":{"count":87},"ENEOS":{"count":736},"Bharat Petroleum":{"count":64},"CAMPSA":{"count":615},"Casey's General Store":{"count":190},"Башнефть":{"count":60},"Kangaroo":{"count":60},"コスモ石油 (COSMO)":{"count":136},"MEROIL":{"count":77},"1-2-3":{"count":71},"出光":{"count":228,"tags":{"name:en":"IDEMITSU"}},"НК Альянс":{"count":88},"Sinclair":{"count":100},"Conoco":{"count":189},"SPBU":{"count":54},"Макпетрол":{"count":109},"Circle K":{"count":166},"Posto Ipiranga":{"count":70},"Posto Shell":{"count":54},"Phoenix":{"count":144},"Ipiranga":{"count":119},"OKKO":{"count":85},"ОККО":{"count":119},"บางจาก":{"count":60},"QuikTrip":{"count":105},"Stewart's":{"count":63},"Posto BR":{"count":68},"ป ต ท":{"count":152},"ปตท":{"count":88},"ANP":{"count":80},"Kum & Go":{"count":80},"Petrolimex":{"count":55},"Sokimex":{"count":66},"Tela":{"count":154},"Posto":{"count":71},"H-E-B":{"count":182},"Укрнафта":{"count":58},"Татнефтепродукт":{"count":54},"Afriquia":{"count":88},"Murphy USA":{"count":67},"昭和シェル (Showa-shell)":{"count":94},"エネオス":{"count":53},"CNG":{"count":94}},"pub":{"Kings Arms":{"count":67},"The Ship":{"count":89},"The White Horse":{"count":204},"The White Hart":{"count":226},"Royal Oak":{"count":150},"The Red Lion":{"count":233},"The Kings Arms":{"count":58},"The Star":{"count":73},"The Anchor":{"count":64},"The Cross Keys":{"count":55},"The Wheatsheaf":{"count":117},"The Crown Inn":{"count":67},"The Kings Head":{"count":53},"The Castle":{"count":62},"The Railway":{"count":102},"The White Lion":{"count":118},"The Bell":{"count":121},"The Bull":{"count":68},"The Plough":{"count":179},"The George":{"count":110},"The Royal Oak":{"count":209},"The Fox":{"count":74},"Prince of Wales":{"count":77},"The Rising Sun":{"count":71},"The Prince of Wales":{"count":51},"The Crown":{"count":244},"The Chequers":{"count":66},"The Swan":{"count":152},"Rose and Crown":{"count":79},"The Victoria":{"count":67},"New Inn":{"count":90},"Royal Hotel":{"count":57},"Red Lion":{"count":207},"Cross Keys":{"count":61},"The Greyhound":{"count":96},"The Black Horse":{"count":94},"The New Inn":{"count":105},"Kings Head":{"count":59},"The Albion":{"count":51},"The Angel":{"count":52},"The Queens Head":{"count":52},"The Ship Inn":{"count":83},"Rose & Crown":{"count":51},"Queens Head":{"count":52},"Irish Pub":{"count":76}},"fast_food":{"Quick":{"count":484},"McDonald's":{"count":12376,"tags":{"cuisine":"burger"}},"Subway":{"count":5576,"tags":{"cuisine":"sandwich"}},"Burger King":{"count":3734,"tags":{"cuisine":"burger"}},"Ali Baba":{"count":61},"Hungry Jacks":{"count":173,"tags":{"cuisine":"burger"}},"Red Rooster":{"count":148},"KFC":{"count":3198,"tags":{"cuisine":"chicken"}},"Domino's Pizza":{"count":985,"tags":{"cuisine":"pizza"}},"Chowking":{"count":142},"Jollibee":{"count":396},"Hesburger":{"count":102},"肯德基":{"count":86},"Wendy's":{"count":1621,"tags":{"cuisine":"burger"}},"Tim Hortons":{"count":323},"Steers":{"count":151},"Hardee's":{"count":268,"tags":{"cuisine":"burger"}},"Arby's":{"count":782},"A&W":{"count":283},"Dairy Queen":{"count":791},"Hallo Pizza":{"count":76},"Fish & Chips":{"count":93},"Harvey's":{"count":90},"麥當勞":{"count":65},"Pizza Pizza":{"count":215},"Kotipizza":{"count":74},"Jack in the Box":{"count":546,"tags":{"cuisine":"burger"}},"Istanbul":{"count":56},"Kochlöffel":{"count":68},"Döner":{"count":228},"Telepizza":{"count":201},"Sibylla":{"count":61},"Carl's Jr.":{"count":298,"tags":{"cuisine":"burger"}},"Quiznos":{"count":266,"tags":{"cuisine":"sandwich"}},"Wimpy":{"count":141},"Sonic":{"count":566,"tags":{"cuisine":"burger"}},"Taco Bell":{"count":1423,"tags":{"cuisine":"mexican"}},"Pizza Nova":{"count":63},"Papa John's":{"count":304,"tags":{"cuisine":"pizza"}},"Nordsee":{"count":159},"Mr. Sub":{"count":103},"Макдоналдс":{"count":324,"tags":{"name:en":"McDonald's"}},"Asia Imbiss":{"count":111},"Chipotle":{"count":290,"tags":{"cuisine":"mexican"}},"マクドナルド":{"count":692,"tags":{"name:en":"McDonald's","cuisine":"burger"}},"In-N-Out Burger":{"count":65},"Jimmy John's":{"count":141},"Jamba Juice":{"count":68},"Робин Сдобин":{"count":82},"Baskin Robbins":{"count":74},"ケンタッキーフライドチキン":{"count":164,"tags":{"name:en":"KFC","cuisine":"chicken"}},"吉野家":{"count":191},"Taco Time":{"count":88},"松屋":{"count":281,"tags":{"name:en":"Matsuya"}},"Little Caesars":{"count":81},"El Pollo Loco":{"count":63},"Del Taco":{"count":141},"White Castle":{"count":80},"Boston Market":{"count":66},"Chick-fil-A":{"count":257,"tags":{"cuisine":"chicken"}},"Panda Express":{"count":238,"tags":{"cuisine":"chinese"}},"Whataburger":{"count":364},"Taco John's":{"count":78},"Теремок":{"count":68},"Culver's":{"count":425},"Five Guys":{"count":141},"Church's Chicken":{"count":95},"Popeye's":{"count":167,"tags":{"cuisine":"chicken"}},"Long John Silver's":{"count":93},"Pollo Campero":{"count":62},"Zaxby's":{"count":51},"すき家":{"count":276,"tags":{"name:en":"SUKIYA"}},"モスバーガー":{"count":257,"tags":{"name:en":"MOS BURGER"}},"Русский Аппетит":{"count":69},"なか卯":{"count":63}},"restaurant":{"Pizza Hut":{"count":1180,"tags":{"cuisine":"pizza"}},"Little Chef":{"count":64},"Adler":{"count":158},"Zur Krone":{"count":90},"Deutsches Haus":{"count":90},"Krone":{"count":171},"Akropolis":{"count":152},"Schützenhaus":{"count":124},"Kreuz":{"count":74},"Waldschänke":{"count":55},"La Piazza":{"count":69},"Lamm":{"count":66},"Zur Sonne":{"count":73},"Zur Linde":{"count":204},"Poseidon":{"count":110},"Shanghai":{"count":82},"Red Lobster":{"count":235},"Zum Löwen":{"count":84},"Swiss Chalet":{"count":107},"Olympia":{"count":74},"Wagamama":{"count":64},"Frankie & Benny's":{"count":66},"Hooters":{"count":103},"Sternen":{"count":78},"Hirschen":{"count":79},"Denny's":{"count":450},"Athen":{"count":68},"Sonne":{"count":126},"Hirsch":{"count":79},"Ratskeller":{"count":150},"La Cantina":{"count":56},"Gasthaus Krone":{"count":56},"El Greco":{"count":86},"Gasthof zur Post":{"count":79},"Nando's":{"count":246},"Löwen":{"count":112},"La Pataterie":{"count":51},"Bella Napoli":{"count":53},"Pizza Express":{"count":262},"Mandarin":{"count":65},"Hong Kong":{"count":83},"Zizzi":{"count":68},"Cracker Barrel":{"count":183},"Rhodos":{"count":81},"Lindenhof":{"count":79},"Milano":{"count":54},"Dolce Vita":{"count":77},"Kirchenwirt":{"count":81},"Kantine":{"count":52},"Ochsen":{"count":95},"Spur":{"count":62},"Mykonos":{"count":59},"Lotus":{"count":66},"Applebee's":{"count":531},"Flunch":{"count":72},"Zur Post":{"count":116},"China Town":{"count":76},"La Dolce Vita":{"count":73},"Waffle House":{"count":207},"Delphi":{"count":88},"Linde":{"count":103},"Outback Steakhouse":{"count":218},"Dionysos":{"count":69},"Kelsey's":{"count":57},"Boston Pizza":{"count":165},"Bella Italia":{"count":132},"Sizzler":{"count":53},"Grüner Baum":{"count":116},"Taj Mahal":{"count":104},"Rössli":{"count":68},"Wimpy":{"count":51},"Traube":{"count":65},"Adria":{"count":52},"Red Robin":{"count":185},"Roma":{"count":61},"San Marco":{"count":67},"Hellas":{"count":55},"La Perla":{"count":67},"Vips":{"count":53},"Panera Bread":{"count":218},"Da Vinci":{"count":54},"Hippopotamus":{"count":96},"Prezzo":{"count":75},"Courtepaille":{"count":106},"Hard Rock Cafe":{"count":70},"Panorama":{"count":61},"デニーズ":{"count":82},"Sportheim":{"count":65},"餃子の王将":{"count":57},"Bären":{"count":60},"Alte Post":{"count":60},"Pizzeria Roma":{"count":51},"China Garden":{"count":66},"Vapiano":{"count":82},"Mamma Mia":{"count":64},"Schwarzer Adler":{"count":57},"IHOP":{"count":317},"Chili's":{"count":328},"Asia":{"count":51},"Olive Garden":{"count":279},"TGI Friday's":{"count":159},"Friendly's":{"count":78},"Buffalo Grill":{"count":202},"Texas Roadhouse":{"count":110},"ガスト":{"count":230,"tags":{"name:en":"Gusto"}},"Sakura":{"count":75},"Mensa":{"count":99},"The Keg":{"count":53},"サイゼリヤ":{"count":93},"La Strada":{"count":52},"Village Inn":{"count":92},"Buffalo Wild Wings":{"count":176},"Peking":{"count":59},"Boston Market":{"count":61},"Round Table Pizza":{"count":53},"Jimmy John's":{"count":69},"California Pizza Kitchen":{"count":61},"Якитория":{"count":77},"Golden Corral":{"count":101},"Perkins":{"count":105},"Ruby Tuesday":{"count":162},"Shari's":{"count":65},"Bob Evans":{"count":129},"바다횟집 (Bada Fish Restaurant)":{"count":55},"Mang Inasal":{"count":84},"Евразия":{"count":102},"ジョナサン":{"count":59},"Longhorn Steakhouse":{"count":66}},"bank":{"Chase":{"count":721},"Commonwealth Bank":{"count":232},"Citibank":{"count":277},"HSBC":{"count":1102},"Barclays":{"count":965},"Westpac":{"count":208},"NAB":{"count":131},"ANZ":{"count":218},"Lloyds Bank":{"count":547},"Landbank":{"count":81},"Sparkasse":{"count":4555},"UCPB":{"count":92},"PNB":{"count":244},"Metrobank":{"count":269},"BDO":{"count":290},"Volksbank":{"count":2591},"BPI":{"count":415},"Postbank":{"count":443},"NatWest":{"count":628},"Raiffeisenbank":{"count":2119},"Yorkshire Bank":{"count":63},"ABSA":{"count":95},"Standard Bank":{"count":109},"FNB":{"count":97},"Deutsche Bank":{"count":855},"SEB":{"count":133},"Commerzbank":{"count":806},"Targobank":{"count":166},"ABN AMRO":{"count":130},"Handelsbanken":{"count":184},"Swedbank":{"count":223},"Kreissparkasse":{"count":600},"UniCredit Bank":{"count":408},"Monte dei Paschi di Siena":{"count":132},"Caja Rural":{"count":99},"Dresdner Bank":{"count":66},"Sparda-Bank":{"count":320},"VÚB":{"count":107},"Slovenská sporiteľňa":{"count":134},"Bank of Montreal":{"count":118},"KBC":{"count":203},"Royal Bank of Scotland":{"count":111},"TSB":{"count":80},"US Bank":{"count":256},"HypoVereinsbank":{"count":561},"Bank Austria":{"count":176},"ING":{"count":496},"Erste Bank":{"count":180},"CIBC":{"count":326},"Scotiabank":{"count":413},"Caisse d'Épargne":{"count":882},"Santander":{"count":1323},"Bank of Scotland":{"count":89},"TD Canada Trust":{"count":450},"BMO":{"count":169},"Danske Bank":{"count":131},"OTP":{"count":192},"Crédit Agricole":{"count":1239},"LCL":{"count":553},"VR-Bank":{"count":430},"ČSOB":{"count":160},"Česká spořitelna":{"count":212},"BNP":{"count":112},"Royal Bank":{"count":65},"Nationwide":{"count":209},"Halifax":{"count":225},"BAWAG PSK":{"count":102},"National Bank":{"count":84},"Nedbank":{"count":80},"First National Bank":{"count":85},"Nordea":{"count":319},"Rabobank":{"count":609},"Sparkasse KölnBonn":{"count":69},"Tatra banka":{"count":67},"Berliner Sparkasse":{"count":62},"Berliner Volksbank":{"count":77},"Wells Fargo":{"count":874},"Credit Suisse":{"count":71},"Société Générale":{"count":634},"Osuuspankki":{"count":75},"Sparkasse Aachen":{"count":56},"Hamburger Sparkasse":{"count":156},"Cassa di Risparmio del Veneto":{"count":68},"BNP Paribas":{"count":617},"Banque Populaire":{"count":433},"BNP Paribas Fortis":{"count":209},"Banco Popular":{"count":291},"Bancaja":{"count":55},"Banesto":{"count":208},"La Caixa":{"count":583},"Santander Consumer Bank":{"count":88},"BRD":{"count":191},"BCR":{"count":143},"Banca Transilvania":{"count":141},"BW-Bank":{"count":97},"Komerční banka":{"count":132},"Banco Pastor":{"count":64},"Stadtsparkasse":{"count":86},"Ulster Bank":{"count":86},"Sberbank":{"count":58},"CIC":{"count":427},"Bancpost":{"count":56},"Caja Madrid":{"count":115},"Maybank":{"count":94},"中国银行":{"count":85},"Unicredit Banca":{"count":243},"Crédit Mutuel":{"count":690},"BBVA":{"count":647},"Intesa San Paolo":{"count":69},"TD Bank":{"count":206},"Belfius":{"count":231},"Bank of America":{"count":924},"RBC":{"count":230},"Alpha Bank":{"count":123},"Сбербанк":{"count":4794},"Россельхозбанк":{"count":201},"Crédit du Nord":{"count":96},"BancoEstado":{"count":80},"Millennium Bank":{"count":414},"State Bank of India":{"count":151},"Беларусбанк":{"count":242},"ING Bank Śląski":{"count":67},"Caixa Geral de Depósitos":{"count":129},"Kreissparkasse Köln":{"count":65},"Banco BCI":{"count":51},"Banco de Chile":{"count":98},"ВТБ24":{"count":326},"UBS":{"count":134},"PKO BP":{"count":265},"Chinabank":{"count":55},"PSBank":{"count":59},"Union Bank":{"count":124},"China Bank":{"count":66},"RCBC":{"count":122},"Unicaja":{"count":83},"BBK":{"count":79},"Ibercaja":{"count":69},"RBS":{"count":143},"Commercial Bank of Ceylon PLC":{"count":79},"Bank of Ireland":{"count":109},"BNL":{"count":87},"Banco Santander":{"count":138},"Banco Itaú":{"count":111},"AIB":{"count":72},"BZ WBK":{"count":77},"Banco do Brasil":{"count":557},"Caixa Econômica Federal":{"count":184},"Fifth Third Bank":{"count":84},"Banca Popolare di Vicenza":{"count":81},"Wachovia":{"count":58},"OLB":{"count":53},"みずほ銀行":{"count":78},"BES":{"count":72},"ICICI Bank":{"count":91},"HDFC Bank":{"count":91},"La Banque Postale":{"count":67},"Pekao SA":{"count":56},"Oberbank":{"count":90},"Bradesco":{"count":295},"Oldenburgische Landesbank":{"count":56},"Bendigo Bank":{"count":93},"Argenta":{"count":86},"AXA":{"count":68},"Axis Bank":{"count":61},"Banco Nación":{"count":67},"GE Money Bank":{"count":72},"Альфа-Банк":{"count":185},"Белагропромбанк":{"count":70},"Caja Círculo":{"count":65},"Banco Galicia":{"count":51},"Eurobank":{"count":97},"Banca Intesa":{"count":62},"Canara Bank":{"count":92},"Cajamar":{"count":77},"Banamex":{"count":149},"Crédit Mutuel de Bretagne":{"count":335},"Davivienda":{"count":83},"Bank Spółdzielczy":{"count":159},"Credit Agricole":{"count":157},"Bankinter":{"count":59},"Banque Nationale":{"count":63},"Bank of the West":{"count":96},"Key Bank":{"count":155},"Western Union":{"count":88},"Citizens Bank":{"count":115},"ПриватБанк":{"count":513},"Security Bank":{"count":78},"Millenium":{"count":60},"Bankia":{"count":149},"三菱東京UFJ銀行":{"count":159},"Caixa":{"count":117},"Banco de Costa Rica":{"count":63},"SunTrust Bank":{"count":73},"Itaú":{"count":338},"PBZ":{"count":52},"中国工商银行":{"count":51},"Bancolombia":{"count":89},"Райффайзен Банк Аваль":{"count":64},"Bancomer":{"count":115},"Banorte":{"count":80},"Alior Bank":{"count":81},"BOC":{"count":51},"Банк Москвы":{"count":118},"ВТБ":{"count":59},"Getin Bank":{"count":55},"Caja Duero":{"count":57},"Regions Bank":{"count":62},"Росбанк":{"count":177},"Banco Estado":{"count":72},"BCI":{"count":68},"SunTrust":{"count":68},"PNC Bank":{"count":254},"신한은행":{"count":217,"tags":{"name:en":"Sinhan Bank"}},"우리은행":{"count":291,"tags":{"name:en":"Uri Bank"}},"국민은행":{"count":165,"tags":{"name:en":"Gungmin Bank"}},"중소기업은행":{"count":52,"tags":{"name:en":"Industrial Bank of Korea"}},"광주은행":{"count":51,"tags":{"name:en":"Gwangju Bank"}},"Газпромбанк":{"count":100},"M&T Bank":{"count":92},"Caja de Burgos":{"count":51},"Santander Totta":{"count":69},"УкрСиббанк":{"count":192},"Ощадбанк":{"count":364},"Уралсиб":{"count":85},"りそな銀行":{"count":225,"tags":{"name:en":"Mizuho Bank"}},"Ecobank":{"count":66},"Cajero Automatico Bancared":{"count":145},"Промсвязьбанк":{"count":93},"三井住友銀行":{"count":129},"Banco Provincia":{"count":67},"BB&T":{"count":147},"Возрождение":{"count":59},"Capital One":{"count":59},"横浜銀行":{"count":51},"Bank Mandiri":{"count":62},"Banco de la Nación":{"count":92},"Banco G&T Continental":{"count":62},"Peoples Bank":{"count":60},"工商银行":{"count":51},"Совкомбанк":{"count":55},"Provincial":{"count":56},"Banco de Desarrollo Banrural":{"count":73},"Banco Bradesco":{"count":65},"Bicentenario":{"count":182},"ლიბერთი ბანკი":{"count":54,"tags":{"name:en":"Liberty Bank"}},"Banesco":{"count":108},"Mercantil":{"count":75},"Bank BRI":{"count":53},"Del Tesoro":{"count":91},"하나은행":{"count":77},"CityCommerce Bank":{"count":71},"De Venezuela":{"count":117}},"car_rental":{"Europcar":{"count":291},"Budget":{"count":92},"Sixt":{"count":161},"Avis":{"count":282},"Hertz":{"count":293},"Enterprise":{"count":199},"stadtmobil CarSharing-Station":{"count":148}},"pharmacy":{"Rowlands Pharmacy":{"count":71},"Boots":{"count":840},"Marien-Apotheke":{"count":314},"Mercury Drug":{"count":426},"Löwen-Apotheke":{"count":356},"Superdrug":{"count":117},"Sonnen-Apotheke":{"count":311},"Rathaus-Apotheke":{"count":132},"Engel-Apotheke":{"count":123},"Hirsch-Apotheke":{"count":83},"Stern-Apotheke":{"count":67},"Lloyds Pharmacy":{"count":295},"Rosen-Apotheke":{"count":208},"Stadt-Apotheke":{"count":302},"Markt-Apotheke":{"count":164},"Аптека":{"count":1989},"Pharmasave":{"count":64},"Brunnen-Apotheke":{"count":53},"Shoppers Drug Mart":{"count":430},"Apotheke am Markt":{"count":60},"Alte Apotheke":{"count":88},"Neue Apotheke":{"count":109},"Gintarinė vaistinė":{"count":101},"Rats-Apotheke":{"count":84},"Adler Apotheke":{"count":313},"Pharmacie Centrale":{"count":64},"Walgreens":{"count":1619},"Rite Aid":{"count":745},"Apotheke":{"count":165},"Linden-Apotheke":{"count":211},"Bahnhof-Apotheke":{"count":66},"Burg-Apotheke":{"count":55},"Jean Coutu":{"count":62},"Pharmaprix":{"count":60},"Farmacias Ahumada":{"count":104},"Farmacia Comunale":{"count":113},"Farmacias Cruz Verde":{"count":86},"Cruz Verde":{"count":99},"Hubertus Apotheke":{"count":52},"CVS":{"count":1560},"Farmacias SalcoBrand":{"count":133},"Фармация":{"count":120},"Bären-Apotheke":{"count":74},"Clicks":{"count":113},"セイジョー":{"count":53},"マツモトキヨシ":{"count":115},"Dr. Max":{"count":51},"Вита":{"count":106},"Радуга":{"count":70},"サンドラッグ":{"count":61},"Apteka":{"count":366},"Первая помощь":{"count":74},"Ригла":{"count":113},"Имплозия":{"count":63},"Kinney Drugs":{"count":68},"Классика":{"count":67},"Ljekarna":{"count":53},"SalcoBrand":{"count":88},"Аптека 36,6":{"count":224},"Фармакор":{"count":75},"スギ薬局":{"count":84},"Аптечный пункт":{"count":148},"Невис":{"count":60},"トモズ (Tomod's)":{"count":83},"Eurovaistinė":{"count":65},"Farmacity":{"count":68},"аптека":{"count":96},"The Generics Pharmacy":{"count":95},"Farmatodo":{"count":123},"Duane Reade":{"count":61},"H-E-B":{"count":262},"Фармленд":{"count":82},"ドラッグてらしま (Drug Terashima)":{"count":96},"Арніка":{"count":125},"ავერსი (Aversi)":{"count":62},"Farmahorro":{"count":58}},"cafe":{"Starbucks":{"count":4238,"tags":{"cuisine":"coffee_shop"}},"Cafeteria":{"count":115},"Costa":{"count":618},"Caffè Nero":{"count":169},"Кафе":{"count":226},"Café Central":{"count":61},"Second Cup":{"count":193},"Dunkin Donuts":{"count":428,"tags":{"cuisine":"donut"}},"Espresso House":{"count":53},"Segafredo":{"count":69},"Coffee Time":{"count":94},"Cafe Coffee Day":{"count":120},"Eiscafe Venezia":{"count":180},"スターバックス":{"count":251,"tags":{"name:en":"Starbucks"}},"Шоколадница":{"count":145},"Pret A Manger":{"count":119},"Столовая":{"count":391},"Jamba Juice":{"count":53},"ドトール":{"count":164,"tags":{"name:en":"DOUTOR"}},"Tchibo":{"count":100},"Кофе Хауз":{"count":104},"Caribou Coffee":{"count":100},"Уют":{"count":51},"Шашлычная":{"count":58},"คาเฟ่ อเมซอน":{"count":62},"Traveler's Coffee":{"count":60},"カフェ・ド・クリエ":{"count":67,"tags":{"name:en":"Cafe de CRIE"}},"Cafe Amazon":{"count":65}}};
18919 var shop = {"supermarket":{"Budgens":{"count":88},"Morrisons":{"count":411},"Interspar":{"count":142},"Merkur":{"count":107},"Sainsbury's":{"count":547},"Lidl":{"count":7130},"Edeka":{"count":2293},"Coles":{"count":400},"Iceland":{"count":315},"Coop":{"count":2100},"Tesco":{"count":1297},"Woolworths":{"count":541},"Zielpunkt":{"count":239},"Nahkauf":{"count":170},"Billa":{"count":1432},"Kaufland":{"count":1004},"Plus":{"count":120},"ALDI":{"count":5172},"Checkers":{"count":128},"Tesco Metro":{"count":137},"NP":{"count":153},"Penny":{"count":1759},"Norma":{"count":1068},"Asda":{"count":225},"Netto":{"count":4379},"Rewe":{"count":2645},"Aldi Süd":{"count":594},"Real":{"count":246},"Tesco Express":{"count":406},"King Soopers":{"count":72},"Kiwi":{"count":167},"Pick n Pay":{"count":241},"ICA":{"count":192},"Tengelmann":{"count":188},"Carrefour":{"count":1640},"Waitrose":{"count":258},"Spar":{"count":2386},"Hofer":{"count":442},"M-Preis":{"count":76},"tegut":{"count":210},"Sainsbury's Local":{"count":118},"E-Center":{"count":66},"Aldi Nord":{"count":210},"nahkauf":{"count":84},"Meijer":{"count":76},"Safeway":{"count":410},"Costco":{"count":152},"Albert":{"count":185},"Jumbo":{"count":194},"Shoprite":{"count":244},"MPreis":{"count":54},"Penny Market":{"count":429},"Tesco Extra":{"count":123},"Albert Heijn":{"count":476},"IGA":{"count":363},"Super U":{"count":488},"Metro":{"count":260},"Neukauf":{"count":77},"Migros":{"count":459},"Marktkauf":{"count":121},"Delikatesy Centrum":{"count":59},"C1000":{"count":307},"Hoogvliet":{"count":53},"Food Basics":{"count":75},"Casino":{"count":264},"Penny Markt":{"count":466},"Giant":{"count":191},"COOP Jednota":{"count":73},"Rema 1000":{"count":368},"Kaufpark":{"count":96},"ALDI SÜD":{"count":113},"Simply Market":{"count":330},"Konzum":{"count":230},"Carrefour Express":{"count":353},"Eurospar":{"count":270},"Mercator":{"count":125},"Famila":{"count":130},"Hemköp":{"count":82},"real,-":{"count":81},"Markant":{"count":88},"Volg":{"count":135},"Leader Price":{"count":267},"Treff 3000":{"count":94},"SuperBrugsen":{"count":67},"Kaiser's":{"count":256},"K+K":{"count":106},"Unimarkt":{"count":86},"Carrefour City":{"count":126},"Sobeys":{"count":122},"S-Market":{"count":109},"Combi":{"count":55},"Denner":{"count":276},"Konsum":{"count":133},"Franprix":{"count":312},"Monoprix":{"count":198},"Diska":{"count":69},"PENNY":{"count":79},"Dia":{"count":835},"Giant Eagle":{"count":85},"NORMA":{"count":115},"AD Delhaize":{"count":63},"Auchan":{"count":152},"Mercadona":{"count":769},"Consum":{"count":130},"Carrefour Market":{"count":80},"Whole Foods":{"count":210,"tags":{"shop":"supermarket"}},"Pam":{"count":56},"sky":{"count":105},"Despar":{"count":146},"Eroski":{"count":208},"Costcutter":{"count":63},"Maxi":{"count":108},"Colruyt":{"count":180},"The Co-operative":{"count":64},"Intermarché":{"count":1210},"Delhaize":{"count":207},"CBA":{"count":176},"Shopi":{"count":53},"Walmart":{"count":644},"Kroger":{"count":317},"Albertsons":{"count":242},"Trader Joe's":{"count":235},"Feneberg":{"count":58},"denn's Biomarkt":{"count":52},"dm":{"count":114},"Kvickly":{"count":55},"Makro":{"count":140},"Dico":{"count":53},"Nah & Frisch":{"count":73},"Champion":{"count":59},"ICA Supermarket":{"count":51},"Fakta":{"count":235},"Магнит":{"count":1760},"Caprabo":{"count":103},"Famiglia Cooperativa":{"count":64},"Народная 7Я семьЯ":{"count":154},"Esselunga":{"count":85},"Maxima":{"count":102},"Petit Casino":{"count":111},"Wasgau":{"count":60},"Pingo Doce":{"count":253},"Match":{"count":140},"Profi":{"count":60},"Lider":{"count":65},"Unimarc":{"count":177},"The Co-operative Food":{"count":190},"Santa Isabel":{"count":128},"Седьмой континент":{"count":79},"HIT":{"count":59},"Rimi":{"count":106},"Conad":{"count":304},"Фуршет":{"count":76},"Willys":{"count":56},"Farmfoods":{"count":64},"U Express":{"count":51},"Фора":{"count":52},"Dunnes Stores":{"count":73},"Сільпо":{"count":125},"マルエツ":{"count":59},"Piggly Wiggly":{"count":57},"Crai":{"count":54},"El Árbol":{"count":73},"Centre Commercial E. Leclerc":{"count":549},"Foodland":{"count":100},"Super Brugsen":{"count":67},"Дикси":{"count":683},"Пятёрочка":{"count":1344},"Publix":{"count":339},"Føtex":{"count":66},"coop":{"count":73},"Fressnapf":{"count":69},"Coop Konsum":{"count":79},"Carrefour Contact":{"count":83},"No Frills":{"count":105},"Plodine":{"count":52},"ADEG":{"count":68},"Minipreço":{"count":111},"Biedronka":{"count":1335},"Eurospin":{"count":155},"Семья":{"count":62},"Gadis":{"count":53},"Евроопт":{"count":68},"Centra":{"count":51},"Квартал":{"count":82},"New World":{"count":69},"Countdown":{"count":95},"Reliance Fresh":{"count":61},"Stokrotka":{"count":98},"Coop Jednota":{"count":74},"Fred Meyer":{"count":64},"Irma":{"count":58},"Continente":{"count":75},"Price Chopper":{"count":99},"Game":{"count":52},"Soriana":{"count":93},"Alimerka":{"count":64},"Piotr i Paweł":{"count":53},"Перекресток":{"count":312},"Maxima X":{"count":117},"Карусель":{"count":55},"ALDI Nord":{"count":51},"Condis":{"count":67},"Sam's Club":{"count":138},"Копейка":{"count":87},"Géant Casino":{"count":54},"ASDA":{"count":180},"Intermarche":{"count":115},"Stop & Shop":{"count":66},"Food Lion":{"count":216},"Harris Teeter":{"count":92},"Foodworks":{"count":62},"Polo Market":{"count":86},"Лента":{"count":51},"西友 (SEIYU)":{"count":58},"H-E-B":{"count":293},"Атак":{"count":53},"Полушка":{"count":139},"Extra":{"count":82},"Lewiatan":{"count":94},"Sigma":{"count":51},"АТБ":{"count":322},"Społem":{"count":55},"Bodega Aurrera":{"count":82},"Tesco Lotus":{"count":77},"Мария-Ра":{"count":108},"Магнолия":{"count":72},"Магазин":{"count":120},"Монетка":{"count":174},"Hy-Vee":{"count":75},"Walmart Supercenter":{"count":133},"Hannaford":{"count":57},"Wegmans":{"count":83},"業務スーパー":{"count":61},"Norfa XL":{"count":55},"ヨークマート (YorkMart)":{"count":64},"Leclerc Drive":{"count":76}},"electronics":{"Media Markt":{"count":285},"Maplin":{"count":65},"Best Buy":{"count":345},"Future Shop":{"count":73},"Saturn":{"count":134},"Currys":{"count":80},"Radio Shack":{"count":269},"Euronics":{"count":115},"Expert":{"count":123},"Эльдорадо":{"count":184},"Darty":{"count":74},"М.Видео":{"count":89},"ヤマダ電機":{"count":51}},"convenience":{"Shell":{"count":255},"Spar":{"count":1119},"McColl's":{"count":100},"Tesco Express":{"count":426},"Sainsbury's Local":{"count":104},"Aral":{"count":56},"One Stop":{"count":146},"The Co-operative Food":{"count":115},"Londis":{"count":352},"7-Eleven":{"count":4440},"CBA":{"count":135},"Coop":{"count":678},"Sale":{"count":80},"Statoil":{"count":69},"Sheetz":{"count":54},"Konzum":{"count":173},"Siwa":{"count":216},"Mercator":{"count":57},"Esso":{"count":67},"COOP Jednota":{"count":181},"Mac's":{"count":152},"Alepa":{"count":62},"Hasty Market":{"count":54},"K-Market":{"count":54},"Costcutter":{"count":292},"Valintatalo":{"count":62},"Casino":{"count":90},"Franprix":{"count":61},"Circle K":{"count":289},"セブンイレブン":{"count":3011,"tags":{"name:en":"7-Eleven"}},"ローソン":{"count":1596,"tags":{"name:en":"LAWSON"}},"BP":{"count":163},"Tesco":{"count":55},"Petit Casino":{"count":233},"Volg":{"count":116},"Mace":{"count":115},"Mini Market":{"count":272},"Nisa Local":{"count":77},"Dorfladen":{"count":75},"Продукты":{"count":4285},"Mini Stop":{"count":228},"LAWSON":{"count":419},"デイリーヤマザキ":{"count":141},"Biedronka":{"count":83},"Надежда":{"count":56},"Mobil":{"count":66},"Nisa":{"count":51},"Premier":{"count":129},"ABC":{"count":152},"ミニストップ":{"count":316,"tags":{"name:en":"MINISTOP"}},"サンクス":{"count":560,"tags":{"name:en":"sunkus"}},"スリーエフ":{"count":88},"8 à Huit":{"count":61},"Tchibo":{"count":56},"Żabka":{"count":546},"Almacen":{"count":229},"Vival":{"count":194},"FamilyMart":{"count":529},"ファミリーマート":{"count":1608,"tags":{"name:en":"FamilyMart"}},"Carrefour City":{"count":57},"Sunkus":{"count":62},"Casey's General Store":{"count":95},"セブンイレブン(Seven-Eleven)":{"count":65},"Jednota":{"count":58},"Магазин":{"count":915},"Гастроном":{"count":152},"Centra":{"count":111},"Магнит":{"count":701},"サークルK":{"count":538,"tags":{"name:en":"Circle K"}},"Wawa":{"count":135},"Proxi":{"count":123},"Универсам":{"count":78},"Перекресток":{"count":51},"Groszek":{"count":65},"Select":{"count":62},"Večerka":{"count":51},"Potraviny":{"count":249},"Смак":{"count":78},"Эконом":{"count":55},"Березка":{"count":77},"Społem":{"count":93},"Carrefour Express":{"count":84},"Cumberland Farms":{"count":63},"Chevron":{"count":59},"Coop Jednota":{"count":66},"Tesco Lotus Express":{"count":67},"Kiosk":{"count":55},"Sklep spożywczy":{"count":130},"24 часа":{"count":58},"Минимаркет":{"count":102},"Oxxo":{"count":669},"Пятёрочка":{"count":398},"abc":{"count":74},"7/11":{"count":51},"Stewart's":{"count":255},"Продукти":{"count":171},"ローソンストア100 (LAWSON STORE 100)":{"count":85},"Дикси":{"count":119},"Радуга":{"count":86},"ローソンストア100":{"count":76},"เซเว่นอีเลฟเว่น":{"count":185},"Delikatesy Centrum":{"count":53},"Citgo":{"count":62},"Фортуна":{"count":51},"Kum & Go":{"count":59},"Мария-Ра":{"count":76},"Picard":{"count":57},"Four Square":{"count":52},"Визит":{"count":57},"Авоська":{"count":55},"Dollar General":{"count":127},"Studenac":{"count":76},"Central Convenience Store":{"count":55},"Монетка":{"count":62},"продукты":{"count":114},"Теремок":{"count":56},"Kwik Trip":{"count":69},"Кулинария":{"count":55},"全家":{"count":90},"Мечта":{"count":54},"Epicerie":{"count":102},"Кировский":{"count":67},"Food Mart":{"count":117},"Delikatesy":{"count":81},"ポプラ":{"count":54},"Lewiatan":{"count":135},"Продуктовый магазин":{"count":149},"Продуктовый":{"count":84},"セイコーマート (Seicomart)":{"count":72},"Виктория":{"count":70},"Весна":{"count":57},"Mini Market Non-Stop":{"count":60},"QuikTrip":{"count":75},"Копеечка":{"count":51},"Royal Farms":{"count":51},"Alfamart":{"count":103},"Indomaret":{"count":141},"магазин":{"count":171},"全家便利商店":{"count":156},"Boutique":{"count":59},"მარკეტი (Market)":{"count":144},"Stores":{"count":61}},"chemist":{"dm":{"count":939},"Müller":{"count":212},"Schlecker":{"count":187},"Etos":{"count":467},"Bipa":{"count":289},"Rossmann":{"count":1669},"DM Drogeriemarkt":{"count":55},"Ihr Platz":{"count":73},"Douglas":{"count":62},"Kruidvat":{"count":123}},"car_repair":{"Peugeot":{"count":83},"Kwik Fit":{"count":128},"ATU":{"count":261},"Midas":{"count":202},"Feu Vert":{"count":113},"Norauto":{"count":152},"Speedy":{"count":115},"Автозапчасти":{"count":212},"Renault":{"count":171},"Pit Stop":{"count":58},"Jiffy Lube":{"count":198},"Шиномонтаж":{"count":1157},"СТО":{"count":395},"O'Reilly Auto Parts":{"count":81},"Carglass":{"count":112},"шиномонтаж":{"count":62},"Citroen":{"count":51},"Euromaster":{"count":87},"Firestone":{"count":88},"Автосервис":{"count":361},"Advance Auto Parts":{"count":52},"Roady":{"count":56}},"furniture":{"IKEA":{"count":169},"Jysk":{"count":109},"Roller":{"count":78},"Dänisches Bettenlager":{"count":309},"Conforama":{"count":99},"Matratzen Concord":{"count":52},"Мебель":{"count":210},"But":{"count":63}},"doityourself":{"Hornbach":{"count":123},"B&Q":{"count":225},"Hubo":{"count":77},"Mr Bricolage":{"count":88},"Gamma":{"count":111},"OBI":{"count":422},"Lowes":{"count":1152},"Wickes":{"count":123},"Hagebau":{"count":59},"Max Bahr":{"count":79},"Castorama":{"count":153},"Rona":{"count":61},"Home Depot":{"count":865},"Toom Baumarkt":{"count":71},"Homebase":{"count":225},"Baumax":{"count":95},"Lagerhaus":{"count":79},"Bauhaus":{"count":186},"Canadian Tire":{"count":97},"Leroy Merlin":{"count":209},"Hellweg":{"count":58},"Brico":{"count":98},"Bricomarché":{"count":235},"Toom":{"count":67},"Hagebaumarkt":{"count":107},"Praktiker":{"count":122},"Menards":{"count":70},"Weldom":{"count":73},"Bunnings Warehouse":{"count":91},"Ace Hardware":{"count":147},"Home Hardware":{"count":72},"Хозтовары":{"count":86},"Стройматериалы":{"count":197},"Bricorama":{"count":60},"Point P":{"count":59}},"stationery":{"Staples":{"count":299},"McPaper":{"count":83},"Office Depot":{"count":98},"Канцтовары":{"count":63}},"car":{"Skoda":{"count":97},"BMW":{"count":149},"Citroen":{"count":277},"Renault":{"count":382},"Mercedes-Benz":{"count":235},"Volvo":{"count":96},"Ford":{"count":239},"Volkswagen":{"count":217},"Mazda":{"count":105},"Mitsubishi":{"count":73},"Fiat":{"count":93},"Автозапчасти":{"count":277},"Opel":{"count":165},"Audi":{"count":121},"Toyota":{"count":271},"Nissan":{"count":189},"Suzuki":{"count":75},"Honda":{"count":157},"Peugeot":{"count":308},"Шиномонтаж":{"count":259},"Hyundai":{"count":166},"Subaru":{"count":58},"Chevrolet":{"count":86},"Автомагазин":{"count":72}},"clothes":{"Matalan":{"count":90},"KiK":{"count":1219},"H&M":{"count":658},"Urban Outfitters":{"count":63},"Vögele":{"count":132},"Zeeman":{"count":121},"Takko":{"count":515},"Adler":{"count":55},"C&A":{"count":506},"Zara":{"count":217},"Vero Moda":{"count":95},"NKD":{"count":486},"Ernsting's family":{"count":312},"Winners":{"count":65},"River Island":{"count":59},"Next":{"count":176},"Gap":{"count":81},"Adidas":{"count":92},"Woolworths":{"count":117},"Mr Price":{"count":88},"Jet":{"count":61},"Pep":{"count":134},"Edgars":{"count":110},"Ackermans":{"count":91},"Truworths":{"count":65},"Ross":{"count":93},"Burton":{"count":51},"Dorothy Perkins":{"count":53},"Deichmann":{"count":61},"Lindex":{"count":73},"s.Oliver":{"count":56},"Cecil":{"count":51},"Dress Barn":{"count":52},"Old Navy":{"count":174},"Jack & Jones":{"count":52},"Pimkie":{"count":73},"Esprit":{"count":231},"Primark":{"count":92},"Bonita":{"count":155},"Mexx":{"count":67},"Gerry Weber":{"count":71},"Tally Weijl":{"count":70},"Mango":{"count":133},"TK Maxx":{"count":84},"Benetton":{"count":101},"Ulla Popken":{"count":61},"AWG":{"count":66},"Tommy Hilfiger":{"count":75},"New Yorker":{"count":180},"Orsay":{"count":73},"Jeans Fritz":{"count":51},"Charles Vögele":{"count":69},"New Look":{"count":126},"Lacoste":{"count":78},"Etam":{"count":53},"Kiabi":{"count":148},"Jack Wolfskin":{"count":60},"American Apparel":{"count":57},"Men's Wearhouse":{"count":54},"Intimissimi":{"count":52},"United Colors of Benetton":{"count":96},"Jules":{"count":63},"Second Hand":{"count":53},"AOKI":{"count":57},"Calzedonia":{"count":68},"洋服の青山":{"count":100},"Levi's":{"count":63},"Celio":{"count":74},"TJ Maxx":{"count":57},"Promod":{"count":82},"Street One":{"count":72},"ユニクロ":{"count":59},"Banana Republic":{"count":57},"Одежда":{"count":75},"Marshalls":{"count":56},"La Halle":{"count":62},"Peacocks":{"count":89},"しまむら":{"count":60}},"books":{"Bruna":{"count":58},"Waterstones":{"count":90},"Libro":{"count":57},"Barnes & Noble":{"count":267},"Weltbild":{"count":74},"Thalia":{"count":121},"Книги":{"count":112}},"department_store":{"Debenhams":{"count":67},"Canadian Tire":{"count":75},"Karstadt":{"count":64},"Walmart":{"count":517},"Kmart":{"count":143},"Target":{"count":574},"Galeria Kaufhof":{"count":61},"Marks & Spencer":{"count":66},"Big W":{"count":57},"Woolworth":{"count":78},"Универмаг":{"count":72},"Sears":{"count":235},"Walmart Supercenter":{"count":101},"Kohl's":{"count":153},"Macy's":{"count":147},"Sam's Club":{"count":54},"JCPenney":{"count":66}},"alcohol":{"Alko":{"count":145},"The Beer Store":{"count":150},"Systembolaget":{"count":210},"LCBO":{"count":239},"Ароматный мир":{"count":62},"Bargain Booze":{"count":62},"Nicolas":{"count":119},"BWS":{"count":70},"Botilleria":{"count":77},"SAQ":{"count":72},"Gall & Gall":{"count":512},"Живое пиво":{"count":70}},"bakery":{"Kamps":{"count":252},"Banette":{"count":52},"Bäckerei Schmidt":{"count":57},"Anker":{"count":73},"Hofpfisterei":{"count":111},"Greggs":{"count":276},"Oebel":{"count":57},"Boulangerie":{"count":266},"Stadtbäckerei":{"count":57},"Steinecke":{"count":145},"Ihle":{"count":76},"Goldilocks":{"count":59},"Dat Backhus":{"count":67},"K&U":{"count":61},"Der Beck":{"count":96},"Thürmann":{"count":54},"Backwerk":{"count":95},"Schäfer's":{"count":51},"Panaderia":{"count":168},"Goeken backen":{"count":51},"Stadtbäckerei Junge":{"count":51},"Boulangerie Patisserie":{"count":119},"Paul":{"count":81},"Хлеб":{"count":89},"Пекарня":{"count":52},"Кулиничи":{"count":51}},"sports":{"Sports Direct":{"count":57},"Decathlon":{"count":309},"Intersport":{"count":283},"Sports Authority":{"count":75},"Спортмастер":{"count":87},"Sport 2000":{"count":90},"Dick's Sporting Goods":{"count":77}},"variety_store":{"Tedi":{"count":157},"Dollarama":{"count":103},"Family Dollar":{"count":61},"Dollar Tree":{"count":110},"Dollar General":{"count":80}},"pet":{"Fressnapf":{"count":318},"PetSmart":{"count":177},"Das Futterhaus":{"count":69},"Pets at Home":{"count":62},"Petco":{"count":101},"Зоомагазин":{"count":100}},"shoes":{"Deichmann":{"count":622},"Reno":{"count":183},"Ecco":{"count":55},"Clarks":{"count":109},"La Halle aux Chaussures":{"count":69},"Brantano":{"count":71},"Geox":{"count":51},"Salamander":{"count":51},"Обувь":{"count":100},"Payless Shoe Source":{"count":67},"Famous Footwear":{"count":59},"Quick Schuh":{"count":72},"Shoe Zone":{"count":55},"Foot Locker":{"count":82},"Bata":{"count":101},"ЦентрОбувь":{"count":51}},"toys":{"La Grande Récré":{"count":56},"Toys R Us":{"count":151,"tags":{"shop":"toys"}},"Intertoys":{"count":57},"Детский мир":{"count":86},"Игрушки":{"count":58}},"travel_agency":{"Flight Centre":{"count":92},"Thomas Cook":{"count":119}},"jewelry":{"Bijou Brigitte":{"count":57},"Christ":{"count":57},"Swarovski":{"count":74}},"optician":{"Fielmann":{"count":232},"Apollo Optik":{"count":150},"Vision Express":{"count":58},"Оптика":{"count":182},"Optic 2000":{"count":98},"Alain Afflelou":{"count":73},"Specsavers":{"count":124},"Krys":{"count":77},"Atol":{"count":55}},"video":{"Blockbuster":{"count":184},"World of Video":{"count":64}},"mobile_phone":{"Билайн":{"count":128},"ソフトバンクショップ (SoftBank shop)":{"count":255},"Vodafone":{"count":355},"O2":{"count":208},"Carphone Warehouse":{"count":127},"Orange":{"count":246},"Verizon Wireless":{"count":125},"Sprint":{"count":109},"T-Mobile":{"count":175},"МТС":{"count":352},"Евросеть":{"count":506},"Bell":{"count":190},"The Phone House":{"count":83},"SFR":{"count":71},"Связной":{"count":439},"Мегафон":{"count":251},"AT&T":{"count":124},"ドコモショップ (docomo shop)":{"count":114},"au":{"count":65},"Movistar":{"count":77},"Bitė":{"count":72}},"hifi":{},"computer":{"PC World":{"count":55},"DNS":{"count":128}},"hairdresser":{"Klier":{"count":119},"Supercuts":{"count":106},"Hairkiller":{"count":51},"Great Clips":{"count":182},"Парикмахерская":{"count":510},"Стиль":{"count":51},"Franck Provost":{"count":70},"Салон красоты":{"count":70}},"hardware":{"1000 мелочей":{"count":61},"Хозтовары":{"count":151},"Стройматериалы":{"count":54}},"motorcycle":{"Yamaha":{"count":67},"Honda":{"count":69}}};
18920 var dataSuggestions = {
18921         amenity: amenity,
18922         shop: shop
18923 };
18924
18925 var dataAddressFormats = [{"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"]]},{"countryCodes":["tw"],"format":[["postcode","city","district"],["place","street"],["housenumber","floor"]]}];
18926
18927 var dataDeprecated = [{"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"}}];
18928
18929 var dataDiscarded = ["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"];
18930
18931 var dataLocales = ["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","ku","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"];
18932
18933 var dataPhoneFormats = {"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"};
18934
18935 var type = "FeatureCollection";
18936 var 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]]]}}];
18937 var dataImperial = {
18938         type: type,
18939         features: features
18940 };
18941
18942 var type$1 = "FeatureCollection";
18943 var features$1 = [{"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]]]}}];
18944 var dataDriveLeft = {
18945         type: type$1,
18946         features: features$1
18947 };
18948
18949 var 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","login":"login","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.","rateLimit":"The API is limiting anonymous connections.  You can fix this by logging in."},"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","documentation_redirect":"This documentation has been redirected to a new page","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":{"done":"done","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_simple":{"label":"Allowed Access"},"access_toilets":{"label":"Access"},"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"}}},"address":{"label":"Address","placeholders":{"city":"City","conscriptionnumber":"123","country":"Country","district":"District","floor":"Floor","hamlet":"Hamlet","housename":"Housename","housenumber":"123","place":"Place","postcode":"Postcode","province":"Province","state":"State","street":"Street","subdistrict":"Subdistrict","suburb":"Suburb"}},"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"},"beauty":{"label":"Shop Type"},"bench":{"label":"Bench"},"bicycle_parking":{"label":"Type"},"bin":{"label":"Waste Bin"},"blood_components":{"label":"Blood Components","options":{"whole":"whole blood","plasma":"plasma","platelets":"platelets","stemcells":"stem cell samples"}},"board_type":{"label":"Type"},"boundary":{"label":"Type"},"brand":{"label":"Brand"},"building_area":{"label":"Building"},"building":{"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"},"cycle_network":{"label":"Network"},"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"}}},"date":{"label":"Date"},"delivery":{"label":"Delivery"},"denomination":{"label":"Denomination"},"denotation":{"label":"Denotation"},"description":{"label":"Description"},"diaper":{"label":"Diaper Changing Available"},"display":{"label":"Display"},"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_multi":{"label":"Fuel Types"},"fuel":{"label":"Fuel"},"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"},"height":{"label":"Height (meters)"},"highway":{"label":"Type"},"historic":{"label":"Type"},"hoops":{"label":"Hoops","placeholder":"1, 2, 4..."},"iata":{"label":"IATA"},"icao":{"label":"ICAO"},"incline_steps":{"label":"Incline","options":{"up":"Up","down":"Down"}},"incline":{"label":"Incline"},"indoor":{"label":"Indoor"},"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_singular":{"label":"Leaf Cycle","options":{"evergreen":"Evergreen","deciduous":"Deciduous","semi_evergreen":"Semi-Evergreen","semi_deciduous":"Semi-Deciduous"}},"leaf_cycle":{"label":"Leaf Cycle","options":{"evergreen":"Evergreen","deciduous":"Deciduous","semi_evergreen":"Semi-Evergreen","semi_deciduous":"Semi-Deciduous","mixed":"Mixed"}},"leaf_type_singular":{"label":"Leaf Type","options":{"broadleaved":"Broadleaved","needleleaved":"Needleleaved","leafless":"Leafless"}},"leaf_type":{"label":"Leaf Type","options":{"broadleaved":"Broadleaved","needleleaved":"Needleleaved","mixed":"Mixed","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"},"map_size":{"label":"Coverage"},"map_type":{"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_bicycle":{"label":"Network Type","placeholder":"Local, Regional, National, International","options":{"lcn":"Local","rcn":"Regional","ncn":"National","icn":"International"}},"network_foot":{"label":"Network Type","placeholder":"Local, Regional, National, International","options":{"lwn":"Local","rwn":"Regional","nwn":"National","iwn":"International"}},"network_horse":{"label":"Network Type","placeholder":"Local, Regional, National, International","options":{"lhn":"Local","rhn":"Regional","nhn":"National","ihn":"International"}},"network_road":{"label":"Network"},"network":{"label":"Network"},"note":{"label":"Note"},"office":{"label":"Type"},"oneway_yes":{"label":"One Way","options":{"undefined":"Assumed to be Yes","yes":"Yes","no":"No"}},"oneway":{"label":"One Way","options":{"undefined":"Assumed to be No","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_supply":{"label":"Power Supply"},"power":{"label":"Type"},"railway":{"label":"Type"},"recycling_accepts":{"label":"Accepts"},"recycling_type":{"label":"Recycling Type","options":{"container":"Container","centre":"Recycling Center"}},"ref":{"label":"Reference"},"relation":{"label":"Type"},"religion":{"label":"Religion"},"restriction":{"label":"Type"},"restrictions":{"label":"Turn Restrictions"},"rooms":{"label":"Rooms"},"route_master":{"label":"Type"},"route":{"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"},"second_hand":{"label":"Sells Used","placeholder":"Yes, No, Only","options":{"yes":"Yes","no":"No","only":"Only"}},"service_rail":{"label":"Service Type","options":{"spur":"Spur","yard":"Yard","siding":"Siding","crossover":"Crossover"}},"service":{"label":"Type"},"service/bicycle":{"label":"Services"},"shelter_type":{"label":"Type"},"shelter":{"label":"Shelter"},"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_ice":{"label":"Sport"},"sport_racing":{"label":"Sport"},"sport":{"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"},"support":{"label":"Support"},"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"},"tower/construction":{"label":"Construction","placeholder":"Guyed, Lattice, Concealed, ..."},"tower/type":{"label":"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_calming":{"label":"Type"},"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"},"visibility":{"label":"Visibility","options":{"house":"Up to 5m (16ft)","street":"5 to 20m (16 to 65ft)","area":"Over 20m (65ft)"}},"water_point":{"label":"Water Point"},"water":{"label":"Type"},"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":{"aerialway":{"name":"Aerialway","terms":"ski lift,funifor,funitel"},"aeroway":{"name":"Aeroway","terms":""},"amenity":{"name":"Amenity","terms":""},"highway":{"name":"Highway","terms":""},"place":{"name":"Place","terms":""},"power":{"name":"Power","terms":""},"railway":{"name":"Railway","terms":""},"roundabout":{"name":"Roundabout","terms":""},"waterway":{"name":"Waterway","terms":""},"address":{"name":"Address","terms":""},"advertising/billboard":{"name":"Billboard","terms":""},"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/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/register_office":{"name":"Register Office","terms":""},"amenity/swimming_pool":{"name":"Swimming Pool","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/coworking_space":{"name":"Coworking Space","terms":"coworking,office"},"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,takeaway"},"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/ice_cream":{"name":"Ice Cream Shop","terms":"gelato,sorbet,sherbet,frozen,yogurt"},"amenity/internet_cafe":{"name":"Internet Cafe","terms":"cybercafe,taxiphone,teleboutique,coffee,cafe,net,lanhouse"},"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_entrance":{"name":"Parking Garage Entrance/Exit","terms":""},"amenity/parking_space":{"name":"Parking Space","terms":""},"amenity/parking":{"name":"Car Parking","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/planetarium":{"name":"Planetarium","terms":"museum,astronomy,observatory"},"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_centre":{"name":"Recycling Center","terms":"bottle,can,dump,glass,garbage,rubbish,scrap,trash"},"amenity/recycling":{"name":"Recycling","terms":"bin,can,bottle,glass,garbage,rubbish,scrap,trash"},"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/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,garbage,rubbish,litter,trash"},"amenity/waste_disposal":{"name":"Garbage Dumpster","terms":"garbage,rubbish,litter,trash"},"amenity/waste_transfer_station":{"name":"Waste Transfer Station","terms":"dump,garbage,recycling,rubbish,scrap,trash"},"amenity/water_point":{"name":"RV Drinking Water","terms":""},"area":{"name":"Area","terms":""},"area/highway":{"name":"Road Surface","terms":""},"barrier":{"name":"Barrier","terms":""},"barrier/entrance":{"name":"Entrance","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/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/bunker":{"name":"Bunker","terms":""},"building/entrance":{"name":"Entrance/Exit","terms":""},"building/train_station":{"name":"Train Station","terms":""},"building/apartments":{"name":"Apartments","terms":""},"building/barn":{"name":"Barn","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/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/university":{"name":"University Building","terms":"college"},"building/warehouse":{"name":"Warehouse","terms":""},"camp_site/camp_pitch":{"name":"Camp Pitch","terms":"tent,rv"},"craft":{"name":"Craft","terms":""},"craft/jeweler":{"name":"Jeweler","terms":""},"craft/locksmith":{"name":"Locksmith","terms":""},"craft/optician":{"name":"Optician","terms":""},"craft/tailor":{"name":"Tailor","terms":"clothes,suit"},"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/key_cutter":{"name":"Key Cutter","terms":""},"craft/metal_construction":{"name":"Metal Construction","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/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/designated":{"name":"Emergency Access Designated","terms":""},"emergency/destination":{"name":"Emergency Access Destination","terms":""},"emergency/no":{"name":"Emergency Access No","terms":""},"emergency/official":{"name":"Emergency Access Official","terms":""},"emergency/private":{"name":"Emergency Access Private","terms":""},"emergency/yes":{"name":"Emergency Access Yes","terms":""},"emergency/ambulance_station":{"name":"Ambulance Station","terms":"EMS,EMT,rescue"},"emergency/defibrillator":{"name":"Defibrillator","terms":"AED"},"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_area":{"name":"Lateral Water Hazard","terms":""},"golf/lateral_water_hazard_line":{"name":"Lateral Water Hazard","terms":""},"golf/rough":{"name":"Rough","terms":""},"golf/tee":{"name":"Tee Box","terms":"teeing ground"},"golf/water_hazard_area":{"name":"Water Hazard","terms":""},"golf/water_hazard_line":{"name":"Water Hazard","terms":""},"healthcare/blood_donation":{"name":"Blood Donor Center","terms":"blood bank,blood donation,blood transfusion,apheresis,plasmapheresis,plateletpheresis,stem cell donation"},"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_junction":{"name":"Motorway Junction / Exit","terms":""},"highway/motorway_link":{"name":"Motorway Link","terms":"ramp,on ramp,off ramp"},"highway/motorway":{"name":"Motorway","terms":""},"highway/path":{"name":"Path","terms":"hike,hiking,trackway,trail,walk"},"highway/pedestrian":{"name":"Pedestrian Street","terms":""},"highway/primary_link":{"name":"Primary Link","terms":"ramp,on ramp,off ramp"},"highway/primary":{"name":"Primary Road","terms":""},"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_link":{"name":"Secondary Link","terms":"ramp,on ramp,off ramp"},"highway/secondary":{"name":"Secondary Road","terms":""},"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_link":{"name":"Tertiary Link","terms":"ramp,on ramp,off ramp"},"highway/tertiary":{"name":"Tertiary Road","terms":""},"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_link":{"name":"Trunk Link","terms":"ramp,on ramp,off ramp"},"highway/trunk":{"name":"Trunk Road","terms":""},"highway/turning_circle":{"name":"Turning Circle","terms":"cul-de-sac"},"highway/turning_loop":{"name":"Turning Loop (Island)","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/farm":{"name":"Farmland","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/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/recreation_ground":{"name":"Recreation Ground","terms":"playing fields"},"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/fitness_centre":{"name":"Gym / Fitness Center","terms":"health,gym,leisure,studio"},"leisure/fitness_centre/yoga":{"name":"Yoga Studio","terms":"studio"},"leisure/fitness_station":{"name":"Outdoor Fitness Station","terms":"fitness,gym"},"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/miniature_golf":{"name":"Miniature Golf","terms":"crazy golf,mini golf,putt-putt"},"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/bowls":{"name":"Bowling Green","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 / Complex","terms":""},"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/embankment":{"name":"Embankment","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/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/pumping_station":{"name":"Pumping Station","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":"cctv"},"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_row":{"name":"Tree row","terms":""},"natural/tree":{"name":"Tree","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/travel_agent":{"name":"Travel Agency","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/government/register_office":{"name":"Register Office","terms":"clerk,marriage,death,birth,certificate"},"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":""},"piste":{"name":"Piste/Ski Trail","terms":"ski,sled,sleigh,snowboard,nordic,downhill,snowmobile"},"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/sub_station":{"name":"Substation","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/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/abandoned":{"name":"Abandoned Railway","terms":""},"railway/crossing":{"name":"Railway Crossing (Path)","terms":"crossing,pedestrian crossing,railroad crossing,level crossing,grade crossing,path through railroad,train crossing"},"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 (Road)","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_entrance":{"name":"Subway Entrance","terms":""},"railway/subway":{"name":"Subway","terms":""},"railway/tram":{"name":"Tram","terms":"streetcar"},"relation":{"name":"Relation","terms":""},"route/ferry":{"name":"Ferry Route","terms":""},"shop":{"name":"Shop","terms":""},"shop/fishmonger":{"name":"Fishmonger","terms":""},"shop/vacant":{"name":"Vacant Shop","terms":""},"shop/alcohol":{"name":"Liquor Store","terms":"alcohol,beer,booze,wine"},"shop/anime":{"name":"Anime Shop","terms":"manga,japan,cosplay,figurine,dakimakura"},"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":"spa,salon,tanning"},"shop/beauty/nails":{"name":"Nail Salon","terms":"manicure,pedicure"},"shop/beauty/tanning":{"name":"Tanning Salon","terms":""},"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":"betting"},"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_parts":{"name":"Car Parts Store","terms":"auto"},"shop/car_repair":{"name":"Car Repair Shop","terms":"auto,garage,service"},"shop/car":{"name":"Car Dealership","terms":"auto"},"shop/carpet":{"name":"Carpet Store","terms":"rug"},"shop/charity":{"name":"Charity Store","terms":"thrift,op shop,nonprofit"},"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/e-cigarette":{"name":"E-Cigarette Shop","terms":"electronic,vapor"},"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/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":"souvenir"},"shop/greengrocer":{"name":"Greengrocer","terms":"fruit,vegetable"},"shop/hairdresser":{"name":"Hairdresser","terms":"barber"},"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":"shopping"},"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":"bike"},"shop/music":{"name":"Music Store","terms":"CD,vinyl"},"shop/musical_instrument":{"name":"Musical Instrument Store","terms":"guitar"},"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/pastry":{"name":"Pastry Shop","terms":"patisserie,cake shop,cakery"},"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/vacuum_cleaner":{"name":"Vacuum Cleaner Store","terms":""},"shop/variety_store":{"name":"Variety Store","terms":""},"shop/video_games":{"name":"Video Game Store","terms":""},"shop/video":{"name":"Video Store","terms":"DVD"},"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/apartment":{"name":"Guest Apartment / Condo","terms":""},"tourism/artwork":{"name":"Artwork","terms":"mural,sculpture,statue"},"tourism/attraction":{"name":"Tourist Attraction","terms":""},"tourism/camp_site":{"name":"Campground","terms":"tent,rv"},"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/information/board":{"name":"Information Board","terms":""},"tourism/information/guidepost":{"name":"Guidepost","terms":""},"tourism/information/map":{"name":"Map","terms":""},"tourism/information/office":{"name":"Tourist Information Office","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":{"name":"Traffic Calming","terms":"bump,hump,slow,speed"},"traffic_calming/bump":{"name":"Speed Bump","terms":"hump,speed,slow"},"traffic_calming/chicane":{"name":"Traffic Chicane","terms":"driveway link,speed,slow"},"traffic_calming/choker":{"name":"Traffic Choker","terms":"speed,slow"},"traffic_calming/cushion":{"name":"Speed Cushion","terms":"bump,hump,speed,slow"},"traffic_calming/dip":{"name":"Dip","terms":"speed,slow"},"traffic_calming/hump":{"name":"Speed Hump","terms":"bump,speed,slow"},"traffic_calming/island":{"name":"Traffic Island","terms":"circle,roundabout,slow"},"traffic_calming/rumble_strip":{"name":"Rumble Strip","terms":"audible lines,sleeper lines,growlers"},"traffic_calming/table":{"name":"Raised Pedestrian Crossing","terms":"flat top,hump,speed,slow"},"type/multipolygon":{"name":"Multipolygon","terms":""},"type/boundary":{"name":"Boundary","terms":""},"type/boundary/administrative":{"name":"Administrative Boundary","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_master":{"name":"Route Master","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/site":{"name":"Site","terms":""},"vertex":{"name":"Other","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":""}}}};
18950
18951 var dataImagery = [{"name":"2013 aerial imagery for San Juan County WA","type":"tms","description":"Public domain aerial imagery taken in May/June 2013 from San Juan County, WA. Resolution is 9 inch.","template":"http://sjcgis.org/arcgis/rest/services/Basemaps/Aerials_2013_WM/MapServer/tile/{zoom}/{y}/{x}","scaleExtent":[0,19],"polygon":[[[-123.274024,48.692975],[-123.007726,48.767256],[-123.007619,48.831577],[-122.783495,48.758416],[-122.693402,48.658522],[-122.767451,48.603606],[-122.744842,48.387083],[-123.248221,48.283531],[-123.114524,48.422614],[-123.219035,48.548575],[-123.274024,48.692975]]],"best":true},{"name":"7th Series (OS7)","type":"tms","template":"http://ooc.openstreetmap.org/os7/{zoom}/{x}/{y}.jpg","polygon":[[[-9,49.8],[-9,61.1],[1.9,61.1],[1.9,49.8],[-9,49.8]]]},{"name":"AGRI black-and-white 2.5m","type":"tms","template":"http://agri.openstreetmap.org/{zoom}/{x}/{y}.png","polygon":[[[112.28778,-28.784589],[112.71488,-31.13894],[114.11263,-34.178287],[113.60788,-37.39012],[117.17992,-37.451794],[119.31538,-37.42096],[121.72262,-36.708394],[123.81925,-35.76893],[125.9547,-34.3066],[127.97368,-33.727398],[130.07031,-33.24166],[130.10913,-33.888704],[131.00214,-34.049705],[131.0798,-34.72257],[132.28342,-35.39],[134.18591,-35.61126],[133.8753,-37.1119],[134.8459,-37.6365],[139.7769,-37.82075],[139.93223,-39.4283],[141.6017,-39.8767],[142.3783,-39.368294],[142.3783,-40.64702],[142.49478,-42.074874],[144.009,-44.060127],[147.23161,-44.03222],[149.05645,-42.534313],[149.52237,-40.99959],[149.9494,-40.852921],[150.8036,-38.09627],[151.81313,-38.12682],[156.20052,-22.667706],[156.20052,-20.10109],[156.62761,-17.417627],[155.26869,-17.19521],[154.14272,-19.51662],[153.5215,-18.34139],[153.05558,-16.5636],[152.78379,-15.256768],[152.27905,-13.4135],[151.3472,-12.391767],[149.48354,-12.05024],[146.9598,-9.992408],[135.9719,-9.992408],[130.3032,-10.33636],[128.09016,-12.164136],[125.91588,-12.315912],[124.3239,-11.860326],[122.03323,-11.974295],[118.26706,-16.9353],[115.93747,-19.11357],[114.0738,-21.11863],[113.49141,-22.596033],[112.28778,-28.784589]]],"terms_text":"AGRI"},{"name":"basemap.at","type":"tms","description":"Basemap of Austria, based on goverment data.","template":"http://maps{switch:1,2,3,4}.wien.gv.at/basemap/geolandbasemap/normal/google3857/{zoom}/{y}/{x}.png","polygon":[[[16.5073284,46.9929304],[16.283417,46.9929304],[16.135839,46.8713046],[15.9831722,46.8190947],[16.0493278,46.655175],[15.8610387,46.7180116],[15.7592608,46.6900933],[15.5607938,46.6796202],[15.5760605,46.6342132],[15.4793715,46.6027553],[15.4335715,46.6516819],[15.2249267,46.6342132],[15.0468154,46.6481886],[14.9908376,46.5887681],[14.9603042,46.6237293],[14.8534374,46.6027553],[14.8330818,46.5012666],[14.7516595,46.4977636],[14.6804149,46.4381781],[14.6142593,46.4381781],[14.578637,46.3785275],[14.4412369,46.4311638],[14.1613476,46.4276563],[14.1257253,46.4767409],[14.0188585,46.4767409],[13.9119917,46.5257813],[13.8254805,46.5047694],[13.4438134,46.560783],[13.3064132,46.5502848],[13.1283019,46.5887681],[12.8433237,46.6132433],[12.7262791,46.6412014],[12.5125455,46.6656529],[12.3598787,46.7040543],[12.3649676,46.7703197],[12.2886341,46.7772902],[12.2733674,46.8852187],[12.2072118,46.8747835],[12.1308784,46.9026062],[12.1156117,46.9998721],[12.2530119,47.0657733],[12.2123007,47.0934969],[11.9833004,47.0449712],[11.7339445,46.9616816],[11.6321666,47.010283],[11.5405665,46.9755722],[11.4998553,47.0068129],[11.418433,46.9651546],[11.2555884,46.9755722],[11.1130993,46.913036],[11.0418548,46.7633482],[10.8891879,46.7598621],[10.7416099,46.7842599],[10.7059877,46.8643462],[10.5787653,46.8399847],[10.4566318,46.8504267],[10.4769874,46.9269392],[10.3853873,46.9894592],[10.2327204,46.8643462],[10.1207647,46.8330223],[9.8663199,46.9408389],[9.9019422,47.0033426],[9.6831197,47.0588402],[9.6118752,47.0380354],[9.6322307,47.128131],[9.5813418,47.1662025],[9.5406306,47.2664422],[9.6067863,47.3492559],[9.6729419,47.369939],[9.6424085,47.4457079],[9.5660751,47.4801122],[9.7136531,47.5282405],[9.7848976,47.5969187],[9.8357866,47.5454185],[9.9477423,47.538548],[10.0902313,47.4491493],[10.1105869,47.3664924],[10.2428982,47.3871688],[10.1869203,47.2698953],[10.3243205,47.2975125],[10.4820763,47.4491493],[10.4311873,47.4869904],[10.4413651,47.5900549],[10.4871652,47.5522881],[10.5482319,47.5351124],[10.5991209,47.5660246],[10.7568766,47.5316766],[10.8891879,47.5454185],[10.9400769,47.4869904],[10.9960547,47.3906141],[11.2352328,47.4422662],[11.2810328,47.3975039],[11.4235219,47.5144941],[11.5761888,47.5076195],[11.6067221,47.5900549],[11.8357224,47.5866227],[12.003656,47.6243647],[12.2072118,47.6037815],[12.1614117,47.6963421],[12.2581008,47.7442718],[12.2530119,47.6792136],[12.4311232,47.7100408],[12.4921899,47.631224],[12.5685234,47.6277944],[12.6295901,47.6894913],[12.7720792,47.6689338],[12.8331459,47.5419833],[12.975635,47.4732332],[13.0417906,47.4938677],[13.0367017,47.5557226],[13.0977685,47.6415112],[13.0316128,47.7100408],[12.9043905,47.7203125],[13.0061684,47.84683],[12.9451016,47.9355501],[12.8636793,47.9594103],[12.8636793,48.0036929],[12.7517236,48.0989418],[12.8738571,48.2109733],[12.9603683,48.2109733],[13.0417906,48.2652035],[13.1842797,48.2990682],[13.2606131,48.2922971],[13.3980133,48.3565867],[13.4438134,48.417418],[13.4387245,48.5523383],[13.509969,48.5860123],[13.6117469,48.5725454],[13.7287915,48.5118999],[13.7847694,48.5725454],[13.8203916,48.6263915],[13.7949471,48.7171267],[13.850925,48.7741724],[14.0595697,48.6633774],[14.0137696,48.6331182],[14.0748364,48.5927444],[14.2173255,48.5961101],[14.3649034,48.5489696],[14.4666813,48.6499311],[14.5582815,48.5961101],[14.5989926,48.6263915],[14.7211261,48.5759124],[14.7211261,48.6868997],[14.822904,48.7271983],[14.8178151,48.777526],[14.9647227,48.7851754],[14.9893637,49.0126611],[15.1485933,48.9950306],[15.1943934,48.9315502],[15.3063491,48.9850128],[15.3928603,48.9850128],[15.4844604,48.9282069],[15.749083,48.8545973],[15.8406831,48.8880697],[16.0086166,48.7808794],[16.2070835,48.7339115],[16.3953727,48.7372678],[16.4920617,48.8110498],[16.6905286,48.7741724],[16.7057953,48.7339115],[16.8991733,48.713769],[16.9755067,48.515271],[16.8482844,48.4511817],[16.8533733,48.3464411],[16.9551512,48.2516513],[16.9907734,48.1498955],[17.0925513,48.1397088],[17.0823736,48.0241182],[17.1739737,48.0207146],[17.0823736,47.8741447],[16.9856845,47.8673174],[17.0823736,47.8092489],[17.0925513,47.7031919],[16.7414176,47.6792136],[16.7057953,47.7511153],[16.5378617,47.7545368],[16.5480395,47.7066164],[16.4208172,47.6689338],[16.573484,47.6175045],[16.670173,47.631224],[16.7108842,47.538548],[16.6599952,47.4491493],[16.5429506,47.3940591],[16.4615283,47.3940591],[16.4920617,47.276801],[16.425906,47.1973317],[16.4717061,47.1489007],[16.5480395,47.1489007],[16.476795,47.0796369],[16.527684,47.0588402],[16.5073284,46.9929304]]],"terms_text":"basemap.at","id":"basemap.at"},{"name":"basemap.at Orthofoto","type":"tms","description":"Orthofoto layer provided by basemap.at. \"Successor\" of geoimage.at imagery.","template":"http://maps{switch:1,2,3,4}.wien.gv.at/basemap/bmaporthofoto30cm/normal/google3857/{zoom}/{y}/{x}.jpeg","polygon":[[[16.5073284,46.9929304],[16.283417,46.9929304],[16.135839,46.8713046],[15.9831722,46.8190947],[16.0493278,46.655175],[15.8610387,46.7180116],[15.7592608,46.6900933],[15.5607938,46.6796202],[15.5760605,46.6342132],[15.4793715,46.6027553],[15.4335715,46.6516819],[15.2249267,46.6342132],[15.0468154,46.6481886],[14.9908376,46.5887681],[14.9603042,46.6237293],[14.8534374,46.6027553],[14.8330818,46.5012666],[14.7516595,46.4977636],[14.6804149,46.4381781],[14.6142593,46.4381781],[14.578637,46.3785275],[14.4412369,46.4311638],[14.1613476,46.4276563],[14.1257253,46.4767409],[14.0188585,46.4767409],[13.9119917,46.5257813],[13.8254805,46.5047694],[13.4438134,46.560783],[13.3064132,46.5502848],[13.1283019,46.5887681],[12.8433237,46.6132433],[12.7262791,46.6412014],[12.5125455,46.6656529],[12.3598787,46.7040543],[12.3649676,46.7703197],[12.2886341,46.7772902],[12.2733674,46.8852187],[12.2072118,46.8747835],[12.1308784,46.9026062],[12.1156117,46.9998721],[12.2530119,47.0657733],[12.2123007,47.0934969],[11.9833004,47.0449712],[11.7339445,46.9616816],[11.6321666,47.010283],[11.5405665,46.9755722],[11.4998553,47.0068129],[11.418433,46.9651546],[11.2555884,46.9755722],[11.1130993,46.913036],[11.0418548,46.7633482],[10.8891879,46.7598621],[10.7416099,46.7842599],[10.7059877,46.8643462],[10.5787653,46.8399847],[10.4566318,46.8504267],[10.4769874,46.9269392],[10.3853873,46.9894592],[10.2327204,46.8643462],[10.1207647,46.8330223],[9.8663199,46.9408389],[9.9019422,47.0033426],[9.6831197,47.0588402],[9.6118752,47.0380354],[9.6322307,47.128131],[9.5813418,47.1662025],[9.5406306,47.2664422],[9.6067863,47.3492559],[9.6729419,47.369939],[9.6424085,47.4457079],[9.5660751,47.4801122],[9.7136531,47.5282405],[9.7848976,47.5969187],[9.8357866,47.5454185],[9.9477423,47.538548],[10.0902313,47.4491493],[10.1105869,47.3664924],[10.2428982,47.3871688],[10.1869203,47.2698953],[10.3243205,47.2975125],[10.4820763,47.4491493],[10.4311873,47.4869904],[10.4413651,47.5900549],[10.4871652,47.5522881],[10.5482319,47.5351124],[10.5991209,47.5660246],[10.7568766,47.5316766],[10.8891879,47.5454185],[10.9400769,47.4869904],[10.9960547,47.3906141],[11.2352328,47.4422662],[11.2810328,47.3975039],[11.4235219,47.5144941],[11.5761888,47.5076195],[11.6067221,47.5900549],[11.8357224,47.5866227],[12.003656,47.6243647],[12.2072118,47.6037815],[12.1614117,47.6963421],[12.2581008,47.7442718],[12.2530119,47.6792136],[12.4311232,47.7100408],[12.4921899,47.631224],[12.5685234,47.6277944],[12.6295901,47.6894913],[12.7720792,47.6689338],[12.8331459,47.5419833],[12.975635,47.4732332],[13.0417906,47.4938677],[13.0367017,47.5557226],[13.0977685,47.6415112],[13.0316128,47.7100408],[12.9043905,47.7203125],[13.0061684,47.84683],[12.9451016,47.9355501],[12.8636793,47.9594103],[12.8636793,48.0036929],[12.7517236,48.0989418],[12.8738571,48.2109733],[12.9603683,48.2109733],[13.0417906,48.2652035],[13.1842797,48.2990682],[13.2606131,48.2922971],[13.3980133,48.3565867],[13.4438134,48.417418],[13.4387245,48.5523383],[13.509969,48.5860123],[13.6117469,48.5725454],[13.7287915,48.5118999],[13.7847694,48.5725454],[13.8203916,48.6263915],[13.7949471,48.7171267],[13.850925,48.7741724],[14.0595697,48.6633774],[14.0137696,48.6331182],[14.0748364,48.5927444],[14.2173255,48.5961101],[14.3649034,48.5489696],[14.4666813,48.6499311],[14.5582815,48.5961101],[14.5989926,48.6263915],[14.7211261,48.5759124],[14.7211261,48.6868997],[14.822904,48.7271983],[14.8178151,48.777526],[14.9647227,48.7851754],[14.9893637,49.0126611],[15.1485933,48.9950306],[15.1943934,48.9315502],[15.3063491,48.9850128],[15.3928603,48.9850128],[15.4844604,48.9282069],[15.749083,48.8545973],[15.8406831,48.8880697],[16.0086166,48.7808794],[16.2070835,48.7339115],[16.3953727,48.7372678],[16.4920617,48.8110498],[16.6905286,48.7741724],[16.7057953,48.7339115],[16.8991733,48.713769],[16.9755067,48.515271],[16.8482844,48.4511817],[16.8533733,48.3464411],[16.9551512,48.2516513],[16.9907734,48.1498955],[17.0925513,48.1397088],[17.0823736,48.0241182],[17.1739737,48.0207146],[17.0823736,47.8741447],[16.9856845,47.8673174],[17.0823736,47.8092489],[17.0925513,47.7031919],[16.7414176,47.6792136],[16.7057953,47.7511153],[16.5378617,47.7545368],[16.5480395,47.7066164],[16.4208172,47.6689338],[16.573484,47.6175045],[16.670173,47.631224],[16.7108842,47.538548],[16.6599952,47.4491493],[16.5429506,47.3940591],[16.4615283,47.3940591],[16.4920617,47.276801],[16.425906,47.1973317],[16.4717061,47.1489007],[16.5480395,47.1489007],[16.476795,47.0796369],[16.527684,47.0588402],[16.5073284,46.9929304]]],"terms_text":"basemap.at","id":"basemap.at orthofoto","best":true},{"name":"Bavaria DOP 80cm","type":"tms","template":"http://mapproxy.osm.ch:8080/tiles/BAYERNDOP80/EPSG900913/{z}/{x}/{y}.png?origin=nw","scaleExtent":[0,18],"polygon":[[[10.1235886,50.568462],[10.1428576,50.5507804],[10.2028056,50.5574195],[10.2520485,50.5179575],[10.3269835,50.4934473],[10.4104825,50.4184762],[10.6031724,50.3310874],[10.6224414,50.2271041],[10.7252093,50.2106649],[10.7294913,50.2476451],[10.8515282,50.2435376],[10.7187863,50.3201525],[10.7123633,50.3652428],[10.8558102,50.3966441],[10.9371682,50.3966441],[10.9906932,50.3666085],[11.1277171,50.3666085],[11.1791011,50.3133169],[11.1619731,50.294172],[11.24119,50.2928042],[11.249754,50.3734364],[11.24119,50.479825],[11.358945,50.5234025],[11.4381619,50.5097889],[11.4424439,50.4893611],[11.425316,50.4771001],[11.425316,50.4416618],[11.4895459,50.4225686],[11.4916869,50.3980089],[11.5195199,50.3980089],[11.5259429,50.3761673],[11.5987369,50.4034677],[11.6372748,50.3884544],[11.7935678,50.4212045],[11.8363877,50.3925494],[11.9220277,50.4280246],[11.9862577,50.3870894],[11.9841167,50.3570478],[12.0483466,50.3310874],[12.0933076,50.3297207],[12.1297046,50.2982751],[12.1404096,50.2722826],[12.1061536,50.255859],[12.1125766,50.2353216],[12.1489736,50.236691],[12.1982166,50.2010728],[12.2239086,50.1640565],[12.2046396,50.1434795],[12.2067806,50.1077916],[12.2431775,50.0995522],[12.2774335,50.0720772],[12.4936744,49.985428],[12.4979564,49.9413559],[12.5557634,49.9220616],[12.5493404,49.8682726],[12.4808284,49.7881677],[12.4101755,49.7577484],[12.4615594,49.7065456],[12.5471994,49.6802313],[12.5878784,49.552613],[12.6542493,49.534553],[12.6628133,49.4330153],[12.7527353,49.4107323],[12.7976963,49.3466124],[12.9047462,49.3563752],[12.9968092,49.3368477],[13.0546161,49.2754251],[13.1316921,49.2195199],[13.1916401,49.1439475],[13.236601,49.1215335],[13.296549,49.1229347],[13.371484,49.0808823],[13.414304,49.0289687],[13.414304,48.9798112],[13.5791609,48.9699739],[13.6348268,48.9432629],[13.6776468,48.8869823],[13.7375948,48.8926132],[13.7846968,48.8334571],[13.8403627,48.774231],[13.8168118,48.7064584],[13.8446447,48.7008065],[13.8425037,48.6003807],[13.7654278,48.5422972],[13.7525818,48.5040106],[13.6712238,48.5054291],[13.6433908,48.5437146],[13.4571239,48.5508013],[13.4571239,48.4159838],[13.40574,48.3605338],[13.283703,48.2751083],[13.0931541,48.2694081],[12.9582712,48.1909669],[12.8769132,48.1852574],[12.7720043,48.0938188],[12.8640672,48.0136764],[12.8983232,47.9549216],[12.9454252,47.9563555],[12.9968092,47.8846147],[13.0139372,47.834337],[12.9347202,47.7321953],[13.0588981,47.7249947],[13.1188461,47.6385093],[13.0653211,47.5692178],[13.0567571,47.473792],[13.0032322,47.4520801],[12.7677223,47.5504355],[12.7698633,47.6327385],[12.7398893,47.6731207],[12.6670953,47.6702373],[12.5750324,47.621195],[12.4808284,47.6197519],[12.4144575,47.6702373],[12.2431775,47.6774455],[12.2132036,47.6918589],[12.1917936,47.6817699],[12.2132036,47.6659119],[12.2110626,47.603875],[12.1746656,47.5952129],[12.1382686,47.603875],[11.8920537,47.603875],[11.8513747,47.5793285],[11.6394158,47.5822169],[11.5944549,47.5489905],[11.5901729,47.5128508],[11.5173789,47.498388],[11.4403029,47.5041736],[11.395342,47.4752392],[11.427457,47.4448409],[11.346099,47.4433929],[11.279728,47.3955873],[11.2133571,47.3883402],[11.247613,47.4318076],[11.1020251,47.3926886],[10.9650012,47.3897897],[10.9778472,47.4361524],[10.9178992,47.4752392],[10.8707972,47.4752392],[10.8558102,47.4940484],[10.9007712,47.5142969],[10.8729382,47.5359831],[10.8108493,47.5128508],[10.6438513,47.5489905],[10.5946084,47.5547705],[10.5796214,47.5287553],[10.4618664,47.5403192],[10.4661484,47.4839212],[10.4875584,47.4781333],[10.4875584,47.4129762],[10.4597254,47.4028333],[10.4597254,47.375293],[10.4104825,47.3738431],[10.4083415,47.3433862],[10.3205605,47.2867768],[10.2820225,47.2780622],[10.2841635,47.2620819],[10.1471396,47.2620819],[10.1921006,47.3027497],[10.1942416,47.3738431],[10.1664086,47.3738431],[10.1664086,47.3462876],[10.1000376,47.3433862],[10.0614996,47.3636928],[10.0679226,47.4187712],[10.0936146,47.426014],[10.0957556,47.4419449],[9.9780007,47.485368],[9.9565907,47.5273097],[9.8945017,47.5287553],[9.8559637,47.5085124],[9.8174258,47.544655],[9.8217078,47.5764399],[9.7746058,47.5822169],[9.7382088,47.525864],[9.6739788,47.5345376],[9.5840569,47.564884],[9.6397228,47.6053186],[9.7167988,47.603875],[9.8559637,47.6760039],[9.9780007,47.6558179],[10.0293846,47.6817699],[10.1000376,47.6673537],[10.1321526,47.6760039],[10.1428576,47.7019459],[10.0614996,47.7725005],[10.1128836,47.8098988],[10.0829096,47.8530173],[10.1086016,47.9090177],[10.0764866,47.9649577],[10.1300116,48.020837],[10.1342936,48.1066872],[10.1000376,48.1281274],[10.0550766,48.2622821],[9.9694367,48.3676462],[10.0315256,48.4259299],[10.0293846,48.461436],[10.1235886,48.4770509],[10.1535626,48.4514968],[10.2349205,48.5125212],[10.3162785,48.516776],[10.2991505,48.6187835],[10.2456255,48.6682961],[10.2734585,48.7064584],[10.3698035,48.6838472],[10.4318924,48.6993935],[10.4511614,48.7276471],[10.4019185,48.7460035],[10.4404564,48.8489571],[10.4340334,48.9587289],[10.3376885,49.0205451],[10.2499075,49.0359872],[10.2499075,49.0738701],[10.2006646,49.1033147],[10.2520485,49.1327418],[10.1235886,49.1971401],[10.1193066,49.2628519],[10.1514216,49.2893915],[10.1043196,49.3452175],[10.1407166,49.3940134],[10.1086016,49.445545],[10.1107426,49.5053651],[10.0722046,49.5331635],[10.0165387,49.4761598],[9.9266167,49.478942],[9.9244757,49.5567797],[9.8987837,49.5817727],[9.8559637,49.5387213],[9.8067208,49.5567797],[9.8666687,49.6067529],[9.8538227,49.6441991],[9.8174258,49.6608327],[9.8345537,49.6899277],[9.7960158,49.7203895],[9.7574778,49.7079302],[9.7403498,49.6857723],[9.7060938,49.7162368],[9.6782608,49.7162368],[9.6825428,49.6885426],[9.6204539,49.6913127],[9.6461458,49.78955],[9.5583649,49.7743431],[9.5712109,49.7356133],[9.5069809,49.7522156],[9.4919939,49.7798735],[9.4684429,49.7605146],[9.425623,49.7784909],[9.404213,49.7646636],[9.33356,49.770195],[9.329278,49.7342295],[9.408495,49.725926],[9.427764,49.6982374],[9.414918,49.6441991],[9.380662,49.6386533],[9.359252,49.6497443],[9.339983,49.6372668],[9.31215,49.648358],[9.277894,49.626173],[9.284317,49.6081403],[9.241497,49.5748315],[9.0980501,49.5720547],[9.0659351,49.6081403],[9.1001911,49.6511305],[9.0916271,49.6926978],[9.1301651,49.7120837],[9.1387291,49.7425316],[9.1087551,49.7563653],[9.1365881,49.7909322],[9.1001911,49.78955],[9.0723581,49.8282367],[9.0359611,49.8351418],[9.0166922,50.0267091],[8.9631672,50.0308352],[8.9567442,50.0597083],[9.0017052,50.0707031],[9.0209742,50.1105378],[9.1216011,50.1228936],[9.1558571,50.1132838],[9.1965361,50.1187753],[9.1858311,50.1352462],[9.235074,50.1475956],[9.37638,50.1270115],[9.408495,50.0816953],[9.5219679,50.095432],[9.5048399,50.1421073],[9.5326729,50.1640565],[9.4898529,50.1695422],[9.4941349,50.2435376],[9.6140309,50.221625],[9.6654148,50.2353216],[9.6354408,50.2490142],[9.6675558,50.2722826],[9.7424908,50.3092151],[9.7296448,50.3584137],[9.7703238,50.4293885],[9.8688097,50.4007384],[9.9180527,50.4089259],[10.0358076,50.479825],[10.0379486,50.5111504],[10.1235886,50.568462]]]},{"name":"Belgium AGIV Orthophoto Flanders","type":"tms","template":"http://tile.informatievlaanderen.be/ws/raadpleegdiensten/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=omwrgbmrvl&STYLE=&FORMAT=image/png&tileMatrixSet=GoogleMapsVL&tileMatrix={zoom}&tileRow={y}&tileCol={x}","scaleExtent":[0,21],"polygon":[[[2.522393220658428,51.101723961331],[3.1260610915867457,51.34117672029327],[3.174929443042849,51.382459567439525],[3.3761520666856217,51.38784154353026],[3.410647373595811,51.33040116175589],[3.4020235468682634,51.28547573497245],[3.4911364230529203,51.256700377228974],[3.4825125963253734,51.30345118353617],[3.5773746903283947,51.323216048914524],[3.813092620881357,51.27288873325703],[3.8217164476089045,51.236906864834886],[3.9309515861578386,51.236906864834886],[4.054559769252684,51.27468708752057],[4.20116482362099,51.35194974615148],[4.169544125619984,51.38066543475199],[4.342020660170932,51.395016527087456],[4.3650175314443915,51.46491366130351],[4.5374940659953396,51.50071687469512],[4.571989372905529,51.479238319799464],[4.560490937268798,51.44879304380801],[4.638105377816725,51.45058450468522],[4.750215125274841,51.5239738914927],[4.8364533925503155,51.507874144493115],[5.080795149830825,51.49892738159079],[5.135412719105292,51.447001512638565],[5.106666630013469,51.391429175957505],[5.264770120018504,51.31782647548482],[5.264770120018504,51.28727359653538],[5.4085005654776275,51.292666758936925],[5.486115006025553,51.325012432665545],[5.5809771000285755,51.28367780302667],[5.583851708937758,51.23510703218069],[5.767826679125435,51.20449910348059],[5.8770618176743685,51.161253258857485],[5.704585283123422,50.80292546633848],[5.905807906766195,50.7865720955422],[5.9374286047672005,50.732019528192964],[5.902933297857012,50.70107817444857],[5.8138204216723555,50.69379488717487],[5.615472406938765,50.761122144578216],[5.500488050571466,50.71200098472672],[5.204403332925673,50.70289881954383],[5.164158808197117,50.67558172042608],[5.037676016193088,50.70107817444857],[4.988807664736986,50.750210783384084],[4.916942442007425,50.72656077355532],[4.790459650003396,50.766576871275696],[4.681224511454462,50.77021300246129],[4.6697260758177315,50.73565834458533],[4.287403090896464,50.67922491935501],[3.91082932379356,50.677403355240585],[3.718230526878334,50.752029520237265],[3.6549891308763196,50.71200098472672],[3.5342555566906557,50.710180693059606],[3.514133294326379,50.741116039142966],[3.45664111614273,50.74384464791457],[3.373277457776438,50.69561581502901],[3.310036061774423,50.70745012302645],[3.2899137994101473,50.7365680045137],[3.1648683118607086,50.742935129324266],[3.1318103094051106,50.77203096207303],[3.080067349039826,50.76021296163662],[2.8745328120332805,50.73929687829333],[2.8960923788521487,50.71109084772858],[2.8745328120332805,50.69561581502901],[2.796918371485353,50.70289881954383],[2.699181668573149,50.80020030189157],[2.6201299235706315,50.79747497850781],[2.5698242676599374,50.85830267681076],[2.5669496587507554,50.923581424665855],[2.6028822701155367,50.94984841176044],[2.549702005295661,50.996006093918574],[2.522393220658428,51.101723961331]]],"terms_text":"Orthophoto Flanders most recent (c) AGIV","best":true},{"name":"Bing aerial imagery","type":"bing","description":"Satellite and aerial imagery.","template":"http://www.bing.com/maps/","scaleExtent":[0,22],"id":"Bing","default":true},{"name":"British Columbia Mosaic","type":"tms","template":"http://{switch:a,b,c,d}.imagery.paulnorman.ca/tiles/bc_mosaic/{zoom}/{x}/{y}.png","scaleExtent":[9,20],"polygon":[[[-123.3176032,49.3272567],[-123.4405258,49.3268222],[-123.440717,49.3384429],[-123.4398375,49.3430357],[-123.4401258,49.3435398],[-123.4401106,49.3439946],[-123.4406265,49.3444493],[-123.4404747,49.3455762],[-123.4397768,49.3460606],[-123.4389726,49.3461298],[-123.4372904,49.3567236],[-123.4374774,49.3710843],[-123.4335292,49.3709446],[-123.4330357,49.373725],[-123.4332717,49.3751221],[-123.4322847,49.3761001],[-123.4317482,49.3791736],[-123.4314264,49.3795927],[-123.4307826,49.3823866],[-123.4313405,49.3827358],[-123.4312118,49.3838533],[-123.4300415,49.3845883],[-123.4189858,49.3847087],[-123.4192235,49.4135198],[-123.3972532,49.4135691],[-123.3972758,49.4243473],[-123.4006929,49.4243314],[-123.4007741,49.5703491],[-123.4000812,49.570345],[-123.4010761,49.5933838],[-123.3760399,49.5932848],[-123.3769811,49.6756063],[-123.3507288,49.6756396],[-123.3507969,49.7086751],[-123.332887,49.708722],[-123.3327888,49.7256288],[-123.3007111,49.7255625],[-123.3009164,49.7375384],[-123.2885986,49.737638],[-123.2887823,49.8249207],[-123.2997955,49.8249207],[-123.3011721,49.8497814],[-123.3218218,49.850669],[-123.3273284,49.8577696],[-123.3276726,49.9758852],[-123.3008279,49.9752212],[-123.3007204,50.0997002],[-123.2501716,50.100735],[-123.25091,50.2754901],[-123.0224338,50.2755598],[-123.0224879,50.3254853],[-123.0009318,50.3254689],[-123.0007778,50.3423899],[-122.9775023,50.3423408],[-122.9774766,50.3504306],[-122.9508137,50.3504961],[-122.950795,50.3711984],[-122.9325221,50.3711521],[-122.9321048,50.399793],[-122.8874234,50.3999748],[-122.8873385,50.4256108],[-122.6620152,50.4256959],[-122.6623083,50.3994506],[-122.5990316,50.3992413],[-122.5988274,50.3755206],[-122.5724832,50.3753706],[-122.5735621,50.2493891],[-122.5990415,50.2494643],[-122.5991504,50.2265663],[-122.6185016,50.2266359],[-122.6185741,50.2244081],[-122.6490609,50.2245126],[-122.6492181,50.1993528],[-122.7308575,50.1993758],[-122.7311583,50.1244287],[-122.7490352,50.1245109],[-122.7490541,50.0903032],[-122.7687806,50.0903435],[-122.7689801,49.9494546],[-122.999047,49.9494706],[-122.9991199,49.8754553],[-122.9775894,49.8754553],[-122.9778145,49.6995098],[-122.9992362,49.6994781],[-122.9992524,49.6516526],[-123.0221525,49.6516526],[-123.0221162,49.5995096],[-123.0491898,49.5994625],[-123.0491898,49.5940523],[-123.0664647,49.5940405],[-123.0663594,49.5451868],[-123.0699906,49.5451202],[-123.0699008,49.5413153],[-123.0706835,49.5392837],[-123.0708888,49.5379931],[-123.0711454,49.5368773],[-123.0711069,49.5358115],[-123.0713764,49.532822],[-123.0716458,49.5321141],[-123.07171,49.5313896],[-123.0720308,49.5304153],[-123.0739554,49.5303486],[-123.0748023,49.5294992],[-123.0748151,49.5288079],[-123.0743403,49.5280584],[-123.073532,49.5274588],[-123.0733652,49.5270423],[-123.0732882,49.5255932],[-123.0737116,49.5249602],[-123.0736218,49.5244938],[-123.0992583,49.5244854],[-123.0991649,49.4754502],[-123.071052,49.4755252],[-123.071088,49.4663034],[-123.0739204,49.4663054],[-123.07422,49.4505028],[-123.0746319,49.4500858],[-123.074651,49.449329],[-123.0745999,49.449018],[-123.0744619,49.4486927],[-123.0743336,49.4479899],[-123.0742427,49.4477688],[-123.0743061,49.4447473],[-123.0747103,49.4447556],[-123.0746384,49.4377306],[-122.9996506,49.4377363],[-122.9996506,49.4369214],[-122.8606163,49.4415314],[-122.8102616,49.4423972],[-122.8098984,49.3766739],[-122.4036093,49.3766617],[-122.4036341,49.3771944],[-122.264739,49.3773028],[-122.263542,49.2360088],[-122.2155742,49.236139],[-122.0580956,49.235878],[-121.9538274,49.2966525],[-121.9400911,49.3045389],[-121.9235761,49.3142257],[-121.8990871,49.3225436],[-121.8883447,49.3259752],[-121.8552982,49.3363575],[-121.832697,49.3441519],[-121.7671336,49.3654361],[-121.6736683,49.3654589],[-121.6404153,49.3743775],[-121.5961976,49.3860493],[-121.5861178,49.3879193],[-121.5213684,49.3994649],[-121.5117375,49.4038378],[-121.4679302,49.4229024],[-121.4416803,49.4345607],[-121.422429,49.4345788],[-121.3462885,49.3932312],[-121.3480144,49.3412388],[-121.5135035,49.320577],[-121.6031683,49.2771727],[-121.6584065,49.1856125],[-121.679953,49.1654109],[-121.7815793,49.0702559],[-121.8076228,49.0622471],[-121.9393997,49.0636219],[-121.9725524,49.0424179],[-121.9921394,49.0332869],[-122.0035289,49.0273413],[-122.0178564,49.0241067],[-122.1108634,48.9992786],[-122.1493067,48.9995305],[-122.1492705,48.9991498],[-122.1991447,48.9996019],[-122.199181,48.9991974],[-122.234365,48.9994829],[-122.234365,49.000173],[-122.3994722,49.0012385],[-122.4521338,49.0016326],[-122.4521338,49.000883],[-122.4584089,49.0009306],[-122.4584814,48.9993124],[-122.4992458,48.9995022],[-122.4992458,48.9992906],[-122.5492618,48.9995107],[-122.5492564,48.9993206],[-122.6580785,48.9994212],[-122.6581061,48.9954007],[-122.7067604,48.9955344],[-122.7519761,48.9956392],[-122.7922063,48.9957204],[-122.7921907,48.9994331],[-123.0350417,48.9995724],[-123.0350437,49.0000958],[-123.0397091,49.0000536],[-123.0397444,49.0001812],[-123.0485506,49.0001348],[-123.0485329,49.0004712],[-123.0557122,49.000448],[-123.0556324,49.0002284],[-123.0641365,49.0001293],[-123.064158,48.9999421],[-123.074899,48.9996928],[-123.0750717,49.0006218],[-123.0899573,49.0003726],[-123.109229,48.9999421],[-123.1271193,49.0003046],[-123.1359953,48.9998741],[-123.1362716,49.0005765],[-123.153851,48.9998061],[-123.1540533,49.0006806],[-123.1710015,49.0001274],[-123.2000916,48.9996849],[-123.2003446,49.0497785],[-123.2108845,49.0497232],[-123.2112218,49.051989],[-123.2070479,49.0520857],[-123.2078911,49.0607884],[-123.2191688,49.0600978],[-123.218958,49.0612719],[-123.2251766,49.0612719],[-123.2253874,49.0622388],[-123.2297088,49.0620316],[-123.2298142,49.068592],[-123.2331869,49.0687301],[-123.2335031,49.0705945],[-123.249313,49.0702493],[-123.2497346,49.0802606],[-123.2751358,49.0803986],[-123.2751358,49.0870947],[-123.299483,49.0873018],[-123.29944,49.080253],[-123.3254508,49.0803944],[-123.3254353,49.1154662],[-123.2750966,49.1503341],[-123.275181,49.1873267],[-123.2788067,49.1871063],[-123.278891,49.1910741],[-123.3004767,49.1910741],[-123.3004186,49.2622933],[-123.3126185,49.2622416],[-123.3125958,49.2714948],[-123.3154251,49.2714727],[-123.3156628,49.2818906],[-123.3174735,49.2818832],[-123.3174961,49.2918488],[-123.3190353,49.2918488],[-123.3190692,49.298602],[-123.3202349,49.2985651],[-123.3202786,49.3019749],[-123.3222679,49.3019605],[-123.3223943,49.3118263],[-123.3254002,49.3118086],[-123.3253898,49.3201721],[-123.3192695,49.3201957],[-123.3192242,49.3246748],[-123.3179437,49.3246596],[-123.3179861,49.3254065],[-123.3176032,49.3272567]]],"terms_url":"http://imagery.paulnorman.ca/tiles/about.html","terms_text":"Copyright Province of British Columbia, City of Surrey"},{"name":"Cambodia, Laos, Thailand, Vietnam bilingual","type":"tms","template":"http://{switch:a,b,c,d}.tile.osm-tools.org/osm_then/{zoom}/{x}/{y}.png","scaleExtent":[0,19],"polygon":[[[97.3,5.6],[97.3,23.4],[109.6,23.4],[109.6,5.6],[97.3,5.6]]],"terms_url":"http://www.osm-tools.org/","terms_text":"© osm-tools.org & OpenStreetMap contributors, CC-BY-SA"},{"name":"City of Cape Town 2015 Aerial","type":"tms","description":"OpenStreetMap use only. City of Cape Town Aerial ortho-photography of the municipal area. 8cm ground sample distance","template":"http://{switch:a,b,c}.coct.aerial.openstreetmap.org.za/layer/za_coct_aerial_2015/{zoom}/{x}/{y}.jpg","scaleExtent":[1,21],"polygon":[[[18.4486565,-33.893623],[18.4485868,-33.902644],[18.4702,-33.9027665],[18.4813902,-33.8472383],[18.4492466,-33.801069],[18.4281537,-33.7356408],[18.43914,-33.7177232],[18.4071895,-33.6589917],[18.3322379,-33.5775191],[18.3324525,-33.5504487],[18.353996,-33.5505918],[18.3542535,-33.5236025],[18.3652398,-33.5236561],[18.3650252,-33.5148009],[18.3760115,-33.5147652],[18.3760545,-33.5058017],[18.4296557,-33.5059449],[18.4296986,-33.4878541],[18.4404919,-33.4878899],[18.4405991,-33.4698849],[18.4943721,-33.4700997],[18.4943292,-33.4791564],[18.5158297,-33.4791743],[18.5157439,-33.4881941],[18.5264727,-33.4883015],[18.5263225,-33.5243538],[18.5479304,-33.5244253],[18.5479519,-33.5153913],[18.5693666,-33.5154987],[18.5693666,-33.524479],[18.5801169,-33.5245327],[18.580074,-33.5425978],[18.5907814,-33.5425978],[18.5907385,-33.5606413],[18.5799453,-33.5605341],[18.5798809,-33.569617],[18.5906956,-33.569617],[18.5906526,-33.5786811],[18.6230108,-33.5787347],[18.622925,-33.5877264],[18.6659691,-33.5878872],[18.6659262,-33.614928],[18.6767194,-33.6149726],[18.6765772,-33.6510279],[18.687298,-33.6510167],[18.6873409,-33.6600365],[18.6980697,-33.6600901],[18.6980697,-33.6690733],[18.7520358,-33.6692519],[18.7520787,-33.6421924],[18.7736437,-33.642246],[18.773708,-33.6331886],[18.8274595,-33.6332958],[18.8275239,-33.6603044],[18.8166663,-33.6602866],[18.8166019,-33.6783233],[18.8058087,-33.6783055],[18.8058087,-33.7053892],[18.8273951,-33.7054428],[18.8273308,-33.7234701],[18.838124,-33.7234344],[18.8380381,-33.7413865],[18.8165161,-33.7413687],[18.8163659,-33.7955057],[18.8055941,-33.7955057],[18.8055083,-33.8135675],[18.794758,-33.8135497],[18.7947151,-33.8315364],[18.7731072,-33.8315186],[18.7731287,-33.8405194],[18.7623569,-33.8405194],[18.7622711,-33.903588],[18.7514564,-33.9035167],[18.7510809,-33.9847823],[18.7619063,-33.9848001],[18.7617776,-34.0298785],[18.772603,-34.0298963],[18.7725815,-34.0389073],[18.7940338,-34.0389406],[18.7938756,-34.0406987],[18.7984461,-34.0411855],[18.8032445,-34.0411788],[18.8034055,-34.0389206],[18.8159367,-34.038974],[18.8163444,-34.0299318],[18.8379845,-34.0316479],[18.8380006,-34.030003],[18.8484183,-34.0300074],[18.8484666,-34.0218491],[18.859925,-34.0234675],[18.8598606,-34.0210132],[18.868272,-34.0220803],[18.8681862,-34.0211733],[18.8854596,-34.0234319],[18.8851806,-34.0213156],[18.9025184,-34.021031],[18.9025828,-34.0119958],[18.9134189,-34.0119958],[18.9134833,-33.9939582],[18.9458844,-33.9940294],[18.9458629,-34.003102],[18.9674279,-34.0029953],[18.9674708,-34.0120848],[18.9782211,-34.0120848],[18.9783284,-34.0211377],[18.9891431,-34.0211377],[18.9891645,-34.039134],[19.0000167,-34.0391251],[19.0000221,-34.0571798],[19.0108368,-34.0572509],[19.0107939,-34.0841436],[19.0000007,-34.0841258],[19.0000221,-34.0931977],[18.9891538,-34.0931711],[18.9891753,-34.1021976],[18.9783177,-34.1021798],[18.9783177,-34.111232],[18.967503,-34.1112143],[18.9674923,-34.1292536],[18.9566025,-34.1292358],[18.9565596,-34.1382408],[18.9674172,-34.1383118],[18.9674172,-34.1473157],[18.9891753,-34.147298],[18.9891753,-34.165303],[18.9782748,-34.1652852],[18.9783177,-34.1742863],[18.9674172,-34.1742685],[18.9674601,-34.1833042],[18.9565596,-34.1833219],[18.9565596,-34.1923565],[18.9457449,-34.192321],[18.945702,-34.2013192],[18.9348659,-34.2013725],[18.9348873,-34.2193305],[18.9023575,-34.2193482],[18.9017567,-34.2362557],[18.8878414,-34.2373467],[18.8894185,-34.2554123],[18.8805887,-34.2553414],[18.8792744,-34.2644348],[18.8696882,-34.2644126],[18.8697097,-34.2734386],[18.8371369,-34.2734208],[18.8371155,-34.2643771],[18.848016,-34.2644037],[18.8480267,-34.237391],[18.8154861,-34.210281],[18.8156471,-34.1741265],[18.8548824,-34.1562743],[18.7617561,-34.0840547],[18.6533734,-34.077479],[18.4797433,-34.1101217],[18.4463713,-34.1342269],[18.4444508,-34.1640868],[18.4359965,-34.1640513],[18.435975,-34.1820172],[18.4468111,-34.182106],[18.4467253,-34.1911052],[18.4659299,-34.1912117],[18.4866151,-34.2453911],[18.4788904,-34.2543659],[18.4860036,-34.2543748],[18.4677109,-34.2994116],[18.4892222,-34.3445792],[18.500112,-34.3445837],[18.4999189,-34.3626174],[18.467432,-34.3625111],[18.4673676,-34.3534947],[18.3916005,-34.3170651],[18.3917722,-34.2900161],[18.3701643,-34.2808678],[18.370682,-34.2178866],[18.3492324,-34.1816178],[18.3274743,-34.1814936],[18.3276674,-34.1634565],[18.3118746,-34.1543832],[18.3114025,-34.1435331],[18.3236656,-34.1346886],[18.3499297,-34.1042053],[18.3393189,-34.0882843],[18.3612487,-34.0597219],[18.3550474,-34.0553843],[18.3427522,-34.064326],[18.3199963,-34.0644326],[18.296071,-34.045126],[18.3068213,-34.0252637],[18.3287725,-34.0191992],[18.3289227,-34.001252],[18.3397374,-34.0012698],[18.3398017,-33.9866282],[18.3628687,-33.9735145],[18.3638129,-33.9292474],[18.3726212,-33.9292741],[18.3728358,-33.917763],[18.3977267,-33.8933469],[18.4486565,-33.893623]]],"terms_url":"https://www.capetown.gov.za","terms_text":"City of Cape Town Aerial - OPENSTREETMAP USE ONLY","best":true},{"name":"Czech CUZK:KM tiles proxy","type":"tms","template":"http://osm-{switch:a,b,c}.zby.cz/tiles_cuzk.php/{zoom}/{x}/{y}.png","scaleExtent":[13,18],"polygon":[[[15.0063684,49.0177392],[15.1559854,49.0013828],[15.190896,48.9424551],[15.3105895,48.9882938],[15.4053469,48.9752013],[15.5400022,48.9162426],[15.7145553,48.8670572],[15.8342488,48.880178],[15.968904,48.8178233],[16.0885976,48.7455261],[16.3978059,48.7455261],[16.4875761,48.8145394],[16.6721036,48.7784014],[16.6820781,48.7356594],[16.9015163,48.7126294],[16.9464014,48.6237005],[17.1159672,48.8375227],[17.2107246,48.880178],[17.4052266,48.8178233],[17.4800351,48.8539329],[17.5299074,48.8178233],[17.7044605,48.8670572],[17.8141796,48.9359033],[17.8840008,48.9359033],[17.9438476,49.0210099],[18.0635412,49.0340903],[18.1184007,49.0994409],[18.1981964,49.3047337],[18.3877112,49.3339917],[18.577226,49.5091747],[18.7567663,49.4994587],[18.8465365,49.5253637],[18.8764598,49.5706645],[18.7966641,49.693412],[18.64206,49.7095399],[18.5872004,49.8351543],[18.6121366,49.8833809],[18.5622643,49.9347695],[18.512392,49.9058702],[18.362775,49.9540261],[18.3278644,49.9219275],[18.2630304,49.9732751],[18.1184007,50.0053395],[18.0635412,50.075806],[17.9139242,49.9796897],[17.779269,50.0309757],[17.714435,50.1237921],[17.6047159,50.1653411],[17.7593201,50.21962],[17.7343839,50.3439092],[17.6396265,50.2802117],[17.3802905,50.2802117],[17.3503671,50.3439092],[17.2805459,50.3375433],[17.1857885,50.4075214],[16.9015163,50.4615247],[16.8666057,50.4138779],[16.9663503,50.3184404],[17.0361715,50.2323826],[16.8366823,50.21962],[16.7120015,50.1046034],[16.5823335,50.1589513],[16.5623846,50.2387626],[16.4327166,50.3375433],[16.3529209,50.3916263],[16.2781124,50.3916263],[16.2082911,50.4456477],[16.3978059,50.5344899],[16.4476782,50.5978464],[16.3529209,50.670601],[16.2382145,50.6769221],[16.2182656,50.6326561],[16.1284954,50.6832425],[16.0486997,50.6073425],[15.988853,50.7021983],[15.8741467,50.6832425],[15.8292616,50.7653291],[15.729517,50.743243],[15.450232,50.8157725],[15.3903852,50.7747914],[15.3804108,50.8598659],[15.2956278,50.8850434],[15.2956278,50.9887568],[15.1709471,51.0201394],[14.9914067,51.0013124],[15.0063684,50.8881896],[14.8417898,50.8756034],[14.7969047,50.8252246],[14.6323261,50.8567177],[14.6622495,50.9353576],[14.5724793,50.9227841],[14.6123772,50.9856174],[14.4976708,51.0483657],[14.4178751,51.0232765],[14.3081561,51.0671736],[14.2532965,51.0044508],[14.4029134,50.9322145],[14.3729901,50.897627],[14.2433221,50.9070625],[14.2084114,50.844123],[14.0338583,50.8126214],[13.9789988,50.8252246],[13.9041903,50.7968626],[13.8742669,50.740087],[13.5351352,50.7243038],[13.530148,50.6579561],[13.4703012,50.6136722],[13.3905055,50.664279],[13.3256715,50.5883483],[13.250863,50.6105074],[13.1960035,50.5059517],[13.0513738,50.5218084],[12.9665909,50.4106997],[12.8269484,50.4710483],[12.7022676,50.4138779],[12.5077656,50.401164],[12.343187,50.2547088],[12.323238,50.1845054],[12.2484296,50.2738373],[12.1736211,50.3311765],[12.0988126,50.33436],[12.1187616,50.25152],[12.2234934,50.1653411],[12.2035445,50.1237921],[12.5027784,49.9732751],[12.4778422,49.9379795],[12.5476634,49.9155052],[12.4678677,49.8029766],[12.408021,49.7611134],[12.4828294,49.6869593],[12.5327017,49.6869593],[12.5177401,49.6288466],[12.6075102,49.5415474],[12.6723442,49.4378793],[12.8119867,49.3469896],[12.9466419,49.3437405],[13.2309141,49.1288206],[13.3256715,49.1059712],[13.4353906,49.0438984],[13.4154417,48.9948387],[13.5002246,48.949006],[13.5650586,48.9882938],[13.6847522,48.8834577],[13.7445989,48.9031312],[13.8243946,48.7751149],[13.8992031,48.7751149],[14.0587945,48.676418],[14.0438328,48.6302932],[14.1435774,48.5907241],[14.3729901,48.5610269],[14.4827091,48.6500662],[14.5774665,48.607215],[14.6273389,48.6335892],[14.7071346,48.5808269],[14.7470324,48.7027561],[14.8118664,48.7389485],[14.8168536,48.794831],[14.9864195,48.7652539],[15.0063684,49.0177392]]],"overlay":true},{"name":"Czech ÚHUL:ORTOFOTO tiles proxy","type":"tms","template":"http://osm-{switch:a,b,c}.zby.cz/tiles_uhul.php/{zoom}/{x}/{y}.jpg","scaleExtent":[13,18],"polygon":[[[15.0063684,49.0177392],[15.1559854,49.0013828],[15.190896,48.9424551],[15.3105895,48.9882938],[15.4053469,48.9752013],[15.5400022,48.9162426],[15.7145553,48.8670572],[15.8342488,48.880178],[15.968904,48.8178233],[16.0885976,48.7455261],[16.3978059,48.7455261],[16.4875761,48.8145394],[16.6721036,48.7784014],[16.6820781,48.7356594],[16.9015163,48.7126294],[16.9464014,48.6237005],[17.1159672,48.8375227],[17.2107246,48.880178],[17.4052266,48.8178233],[17.4800351,48.8539329],[17.5299074,48.8178233],[17.7044605,48.8670572],[17.8141796,48.9359033],[17.8840008,48.9359033],[17.9438476,49.0210099],[18.0635412,49.0340903],[18.1184007,49.0994409],[18.1981964,49.3047337],[18.3877112,49.3339917],[18.577226,49.5091747],[18.7567663,49.4994587],[18.8465365,49.5253637],[18.8764598,49.5706645],[18.7966641,49.693412],[18.64206,49.7095399],[18.5872004,49.8351543],[18.6121366,49.8833809],[18.5622643,49.9347695],[18.512392,49.9058702],[18.362775,49.9540261],[18.3278644,49.9219275],[18.2630304,49.9732751],[18.1184007,50.0053395],[18.0635412,50.075806],[17.9139242,49.9796897],[17.779269,50.0309757],[17.714435,50.1237921],[17.6047159,50.1653411],[17.7593201,50.21962],[17.7343839,50.3439092],[17.6396265,50.2802117],[17.3802905,50.2802117],[17.3503671,50.3439092],[17.2805459,50.3375433],[17.1857885,50.4075214],[16.9015163,50.4615247],[16.8666057,50.4138779],[16.9663503,50.3184404],[17.0361715,50.2323826],[16.8366823,50.21962],[16.7120015,50.1046034],[16.5823335,50.1589513],[16.5623846,50.2387626],[16.4327166,50.3375433],[16.3529209,50.3916263],[16.2781124,50.3916263],[16.2082911,50.4456477],[16.3978059,50.5344899],[16.4476782,50.5978464],[16.3529209,50.670601],[16.2382145,50.6769221],[16.2182656,50.6326561],[16.1284954,50.6832425],[16.0486997,50.6073425],[15.988853,50.7021983],[15.8741467,50.6832425],[15.8292616,50.7653291],[15.729517,50.743243],[15.450232,50.8157725],[15.3903852,50.7747914],[15.3804108,50.8598659],[15.2956278,50.8850434],[15.2956278,50.9887568],[15.1709471,51.0201394],[14.9914067,51.0013124],[15.0063684,50.8881896],[14.8417898,50.8756034],[14.7969047,50.8252246],[14.6323261,50.8567177],[14.6622495,50.9353576],[14.5724793,50.9227841],[14.6123772,50.9856174],[14.4976708,51.0483657],[14.4178751,51.0232765],[14.3081561,51.0671736],[14.2532965,51.0044508],[14.4029134,50.9322145],[14.3729901,50.897627],[14.2433221,50.9070625],[14.2084114,50.844123],[14.0338583,50.8126214],[13.9789988,50.8252246],[13.9041903,50.7968626],[13.8742669,50.740087],[13.5351352,50.7243038],[13.530148,50.6579561],[13.4703012,50.6136722],[13.3905055,50.664279],[13.3256715,50.5883483],[13.250863,50.6105074],[13.1960035,50.5059517],[13.0513738,50.5218084],[12.9665909,50.4106997],[12.8269484,50.4710483],[12.7022676,50.4138779],[12.5077656,50.401164],[12.343187,50.2547088],[12.323238,50.1845054],[12.2484296,50.2738373],[12.1736211,50.3311765],[12.0988126,50.33436],[12.1187616,50.25152],[12.2234934,50.1653411],[12.2035445,50.1237921],[12.5027784,49.9732751],[12.4778422,49.9379795],[12.5476634,49.9155052],[12.4678677,49.8029766],[12.408021,49.7611134],[12.4828294,49.6869593],[12.5327017,49.6869593],[12.5177401,49.6288466],[12.6075102,49.5415474],[12.6723442,49.4378793],[12.8119867,49.3469896],[12.9466419,49.3437405],[13.2309141,49.1288206],[13.3256715,49.1059712],[13.4353906,49.0438984],[13.4154417,48.9948387],[13.5002246,48.949006],[13.5650586,48.9882938],[13.6847522,48.8834577],[13.7445989,48.9031312],[13.8243946,48.7751149],[13.8992031,48.7751149],[14.0587945,48.676418],[14.0438328,48.6302932],[14.1435774,48.5907241],[14.3729901,48.5610269],[14.4827091,48.6500662],[14.5774665,48.607215],[14.6273389,48.6335892],[14.7071346,48.5808269],[14.7470324,48.7027561],[14.8118664,48.7389485],[14.8168536,48.794831],[14.9864195,48.7652539],[15.0063684,49.0177392]]],"terms_text":"Ortofoto public domain ÚHUL, year 2000"},{"name":"Danube flood ortophoto 2013","type":"tms","template":"http://e.tile.openstreetmap.hu/dunai-arviz-2013/{zoom}/{x}/{y}.jpg","scaleExtent":[10,20],"polygon":[[[19.0773152,47.6959718],[19.0779881,47.6959835],[19.0946205,47.6944562],[19.0805603,47.595874],[19.0743376,47.5890907],[19.0795196,47.5888284],[19.07717,47.5724109],[19.0577884,47.5720924],[19.0773152,47.6959718]]],"terms_url":"http://fototerkep.hu/","terms_text":"Fotótérkép.hu"},{"name":"FÖMI ortofotó 2000","type":"tms","description":"Hungary","template":"http://e.tile.openstreetmap.hu/ortofoto2000/{zoom}/{x}/{y}.jpg","scaleExtent":[0,17],"polygon":[[[16.1139147,46.8691038],[16.1789749,46.90662],[16.2000429,46.9415079],[16.2217547,46.9355441],[16.2462784,46.9463851],[16.2553226,46.9642125],[16.2764694,46.9626082],[16.290583,47.0139849],[16.3016199,46.9992329],[16.3414618,46.9965225],[16.3505162,47.0106313],[16.3734016,46.9985929],[16.412765,47.00475],[16.4332705,46.9927417],[16.4478119,47.003893],[16.479997,46.9941169],[16.5121988,47.0011695],[16.4635584,47.0322699],[16.4478586,47.0227481],[16.439123,47.029663],[16.445673,47.038872],[16.520323,47.056103],[16.473213,47.0736169],[16.4637199,47.09392],[16.500798,47.110058],[16.500035,47.123295],[16.5295349,47.1287419],[16.5171609,47.1496938],[16.454951,47.1425878],[16.4648728,47.1683349],[16.4555643,47.1875584],[16.4305559,47.1847022],[16.4195013,47.1949147],[16.4189215,47.2107114],[16.4371293,47.2097043],[16.4426335,47.2337117],[16.4313127,47.2527554],[16.4671512,47.2531652],[16.4892319,47.2798885],[16.4646338,47.3338455],[16.4337002,47.3528101],[16.458513,47.3670496],[16.4454619,47.4070195],[16.4831657,47.4093628],[16.4963821,47.3892659],[16.5170941,47.4100218],[16.5749054,47.4054243],[16.5807291,47.4191699],[16.661847,47.455595],[16.6706419,47.47422],[16.6523395,47.500342],[16.6895619,47.510161],[16.7147797,47.540199],[16.663545,47.567733],[16.673199,47.6049544],[16.6595343,47.6061018],[16.652758,47.622852],[16.6314207,47.6283176],[16.5739108,47.619667],[16.5147382,47.6461964],[16.4967504,47.6393149],[16.425464,47.6621679],[16.4437449,47.674205],[16.4480507,47.6964725],[16.4746984,47.6811576],[16.4872245,47.6979767],[16.5521729,47.7225519],[16.5363779,47.736785],[16.5479799,47.751544],[16.6095193,47.7603722],[16.6344148,47.7590843],[16.65729,47.7414879],[16.7209405,47.7353565],[16.7534062,47.6828165],[16.8301587,47.681058],[16.8394284,47.7045139],[16.8668943,47.7211462],[16.876679,47.6876452],[17.0937421,47.7077706],[17.0706562,47.7285366],[17.0516019,47.7938499],[17.0749479,47.8084997],[17.047139,47.8285635],[17.0519452,47.8377691],[17.0105513,47.8581765],[17.0163878,47.8673325],[17.0857537,47.8746239],[17.113171,47.9271605],[17.0917133,47.9342916],[17.1183782,47.9601083],[17.094657,47.9708775],[17.2010289,48.019992],[17.241769,48.0224651],[17.257955,47.998655],[17.334651,47.993125],[17.4029929,47.947849],[17.4539199,47.8852579],[17.5267369,47.865509],[17.5675779,47.8151289],[17.608402,47.8218859],[17.7085789,47.756678],[17.7798739,47.739487],[17.8660959,47.74575],[17.9001292,47.7392633],[17.946867,47.744668],[17.9708709,47.7578392],[18.0044103,47.7463402],[18.0380583,47.7576812],[18.2958774,47.7314616],[18.4540681,47.7651226],[18.4931553,47.7527552],[18.5590761,47.7659963],[18.6460866,47.7590921],[18.7260691,47.7890411],[18.7411784,47.8138245],[18.7920013,47.8230869],[18.8485417,47.8167221],[18.855876,47.826077],[18.828014,47.834291],[18.8135749,47.85555],[18.76353,47.8716049],[18.756858,47.896838],[18.776746,47.955092],[18.7552499,47.9763469],[18.8157429,47.993442],[18.819998,48.039676],[18.833268,48.048239],[18.8749364,48.0470707],[18.886674,48.058682],[18.9089819,48.051139],[18.9439039,48.058865],[18.9816099,48.0536009],[19.0148639,48.078179],[19.0585249,48.0573529],[19.0843619,48.072781],[19.107402,48.065596],[19.1352889,48.074146],[19.2413679,48.0536529],[19.2557819,48.0715559],[19.3031119,48.088711],[19.3865969,48.091914],[19.400018,48.082304],[19.454053,48.101436],[19.467354,48.083933],[19.4944199,48.109906],[19.492377,48.1396639],[19.5128219,48.154663],[19.504518,48.173443],[19.528967,48.190358],[19.526044,48.20313],[19.577502,48.2160149],[19.6308263,48.2500725],[19.6445239,48.2391719],[19.669857,48.239212],[19.691219,48.203894],[19.721125,48.201473],[19.74618,48.2165119],[19.7871629,48.19253],[19.7987329,48.19482],[19.8052829,48.183733],[19.782415,48.165039],[19.794812,48.153529],[19.821331,48.169081],[19.8452819,48.162742],[19.8551729,48.178431],[19.8601309,48.169409],[19.898745,48.1663119],[19.9145359,48.146863],[19.898298,48.1249019],[19.937383,48.131118],[19.9743939,48.1660049],[19.988706,48.1621679],[20.029038,48.1776849],[20.049449,48.1671999],[20.0729859,48.179606],[20.0700369,48.1917019],[20.1340909,48.225182],[20.1331879,48.253982],[20.206162,48.250979],[20.2038299,48.261906],[20.228466,48.262779],[20.2349469,48.279933],[20.286858,48.26164],[20.3257109,48.272794],[20.3374649,48.301667],[20.3656579,48.316606],[20.384077,48.3511809],[20.4098349,48.365857],[20.402532,48.382565],[20.4205349,48.403858],[20.416228,48.418536],[20.507929,48.489363],[20.5065069,48.534415],[20.537471,48.527878],[20.5464939,48.544292],[20.586595,48.535759],[20.6538739,48.561413],[20.836359,48.58284],[20.8378,48.57421],[20.8504359,48.5816329],[20.8453301,48.5665046],[20.8681549,48.551818],[20.922323,48.559453],[20.9346349,48.538341],[20.955882,48.533963],[20.9561979,48.521666],[20.9815849,48.5177669],[21.0151139,48.532313],[21.0663209,48.525894],[21.1174479,48.4910549],[21.1608749,48.521499],[21.179634,48.518232],[21.221061,48.537497],[21.305488,48.5222489],[21.313377,48.550841],[21.326875,48.554129],[21.319384,48.561201],[21.4154499,48.558951],[21.4226649,48.578821],[21.4406099,48.585104],[21.514091,48.551065],[21.5420199,48.508395],[21.6139329,48.509416],[21.6201879,48.469826],[21.663549,48.417961],[21.6645609,48.392164],[21.7017409,48.380695],[21.711871,48.357617],[21.8174139,48.332787],[21.8352029,48.3346409],[21.837213,48.363253],[21.8842979,48.356047],[21.8848429,48.367539],[21.897883,48.36256],[21.8997959,48.3702229],[21.9281859,48.3615969],[21.9268059,48.370899],[21.949198,48.378728],[21.994463,48.377323],[22.0213259,48.392749],[22.0546049,48.377528],[22.0764859,48.387241],[22.086743,48.371564],[22.1359089,48.380519],[22.131056,48.3912329],[22.152768,48.3962409],[22.1561913,48.4093076],[22.2125722,48.4256468],[22.2371405,48.4100396],[22.2654858,48.4098675],[22.2398761,48.3870055],[22.2675722,48.3611612],[22.3178106,48.3545437],[22.3132861,48.3250712],[22.3372944,48.3079113],[22.3384267,48.2792074],[22.3847547,48.2339632],[22.4006407,48.249198],[22.4328384,48.2525166],[22.456386,48.2423109],[22.4899029,48.2534237],[22.4972201,48.2395546],[22.5161491,48.237965],[22.5311088,48.2094282],[22.5711442,48.1961428],[22.5616362,48.1816066],[22.5982449,48.144756],[22.5902763,48.1073414],[22.6754492,48.091997],[22.7347192,48.119848],[22.7576242,48.1200599],[22.7703914,48.1090162],[22.772319,48.1218742],[22.8027688,48.1221112],[22.8025285,48.1070813],[22.8254256,48.1175119],[22.8364365,48.080249],[22.8611284,48.0750312],[22.8677955,48.0524256],[22.8820424,48.0548053],[22.8659692,48.0113165],[22.835562,47.9905988],[22.8407599,47.9813636],[22.8725729,47.9752683],[22.8697274,47.9659593],[22.8915652,47.9672446],[22.897435,47.9540629],[22.8473299,47.9077579],[22.7928135,47.8908586],[22.7586924,47.8941446],[22.77775,47.8422508],[22.7136344,47.8360928],[22.6801938,47.7877527],[22.6111171,47.7717455],[22.5490018,47.7722246],[22.4812121,47.8108886],[22.4513078,47.803389],[22.4313319,47.7398119],[22.3566167,47.7486206],[22.3177714,47.7660887],[22.3176236,47.7433657],[22.2851369,47.7292757],[22.264325,47.7310675],[22.2589955,47.6979057],[22.2306796,47.693196],[22.1796501,47.5916115],[22.1289245,47.5978984],[22.0942787,47.5583628],[22.0782587,47.5621299],[22.0534529,47.5474795],[22.0712176,47.5380742],[22.0617872,47.5288029],[22.0451278,47.5398919],[22.0367222,47.5326653],[22.0071886,47.48362],[22.0327909,47.4508372],[22.0238835,47.3908631],[22.0119849,47.3758016],[21.9627373,47.381053],[21.9382461,47.3725317],[21.8777922,47.2857763],[21.8872845,47.2730473],[21.8534909,47.2397622],[21.8580662,47.1873597],[21.8124804,47.1667511],[21.7924092,47.1059751],[21.7268258,47.0983882],[21.6976037,47.057915],[21.6504151,47.0408303],[21.6888701,47.0019977],[21.6678744,46.9712337],[21.6814917,46.9652089],[21.6381964,46.9330487],[21.5984455,46.9274708],[21.6142857,46.8867275],[21.6016694,46.8668202],[21.520328,46.8373749],[21.5186086,46.8000703],[21.4831761,46.7650246],[21.5263389,46.7393249],[21.529369,46.7209721],[21.4923253,46.6859652],[21.4728438,46.6959075],[21.4299047,46.693937],[21.4309553,46.6781367],[21.4546661,46.660863],[21.4162375,46.6426231],[21.4097959,46.6218052],[21.3657038,46.6379501],[21.3300499,46.6318155],[21.3139733,46.617666],[21.3012351,46.5908672],[21.3207905,46.5828562],[21.2743045,46.5407362],[21.2600254,46.5021583],[21.2744188,46.4767333],[21.2964506,46.4762973],[21.3174343,46.4507288],[21.2895176,46.4154784],[21.2963256,46.4069601],[21.2250116,46.4136899],[21.2064214,46.4033825],[21.1992563,46.3479034],[21.1762269,46.3357664],[21.180497,46.3044494],[21.1155437,46.3018529],[21.1030549,46.2624637],[21.0708792,46.2539014],[21.0660827,46.2429394],[21.0366237,46.2480392],[21.0246723,46.2665329],[20.960817,46.2623039],[20.9465849,46.2793024],[20.9250701,46.2766191],[20.9218133,46.2618129],[20.8732713,46.2877555],[20.7756538,46.2759602],[20.7490474,46.2508489],[20.7618619,46.204563],[20.727401,46.2077485],[20.7341052,46.1939355],[20.7140487,46.1660531],[20.6843592,46.1447802],[20.6549178,46.1497739],[20.6394471,46.1267602],[20.5450486,46.1790935],[20.5014839,46.190334],[20.4949436,46.1709908],[20.4592293,46.1428837],[20.3975133,46.1574709],[20.3685325,46.1528554],[20.3557074,46.1696256],[20.2968136,46.1521542],[20.2549024,46.1158522],[20.2484757,46.1300956],[20.2330132,46.1241668],[20.1817362,46.1601137],[20.1364966,46.1449476],[20.1009667,46.1772756],[20.0636156,46.1437275],[20.0346142,46.1458888],[20.0158072,46.1768354],[19.9354075,46.1764243],[19.8533469,46.1500005],[19.8179747,46.1281652],[19.7585403,46.1479754],[19.6982054,46.1879317],[19.6827672,46.1800388],[19.661508,46.1904394],[19.6317396,46.1692993],[19.5676482,46.179106],[19.5604013,46.1665762],[19.5026585,46.1424492],[19.5271208,46.1210269],[19.4645033,46.0953827],[19.4665828,46.0820437],[19.4160037,46.0460453],[19.3803957,46.0358749],[19.3640923,46.0522965],[19.2819012,46.0148048],[19.2965348,45.9881173],[19.2856472,45.9968981],[19.1479857,45.9963445],[19.1338422,46.0370993],[19.104873,46.0401673],[19.0660427,46.0001999],[19.0796791,45.9636376],[19.0059803,45.9590674],[19.0092745,45.9236559],[18.9061334,45.9353801],[18.8794572,45.9166827],[18.8647137,45.9208493],[18.8685629,45.9113361],[18.8276792,45.9051714],[18.8220041,45.9145893],[18.8075092,45.9036055],[18.809247,45.8796189],[18.7956242,45.8784488],[18.7048857,45.9181883],[18.6700246,45.9108439],[18.6596602,45.9168934],[18.6651348,45.899279],[18.6412808,45.8890396],[18.6550179,45.8742393],[18.6277704,45.8733782],[18.6148449,45.8531438],[18.6236656,45.8398531],[18.5732391,45.8137578],[18.5749849,45.8004344],[18.559716,45.8037961],[18.5223504,45.7826858],[18.4906706,45.7947167],[18.4821905,45.7655032],[18.4562828,45.7695229],[18.4450763,45.7605195],[18.446853,45.737128],[18.40763,45.7397119],[18.3918949,45.7616983],[18.3642257,45.7729364],[18.3394214,45.7471605],[18.2968157,45.7612196],[18.2440473,45.7612305],[18.2307311,45.7790328],[18.1908702,45.7878759],[18.1681939,45.7762712],[18.1246514,45.7896277],[18.1068067,45.7708256],[18.0818922,45.7645205],[17.9958808,45.7957311],[17.9302095,45.7863301],[17.9066757,45.7925692],[17.8653145,45.7670064],[17.8262748,45.8099957],[17.8089784,45.8040989],[17.7809054,45.8174884],[17.7603399,45.811923],[17.7408624,45.8295975],[17.6632915,45.8381849],[17.6276211,45.8979446],[17.5700676,45.9358204],[17.4378254,45.9503823],[17.4258964,45.9272681],[17.4108059,45.9399665],[17.392149,45.9302149],[17.3828713,45.9475733],[17.3476208,45.9423413],[17.3438769,45.9605329],[17.3537711,45.9525011],[17.3905375,45.9581914],[17.387423,45.9661823],[17.3583539,45.9642737],[17.3754852,45.9686921],[17.3751895,45.9881054],[17.3635685,45.9915442],[17.3567202,45.9735836],[17.3339583,45.9960781],[17.3319847,45.9728948],[17.3129974,45.9665347],[17.323647,45.9887776],[17.2987653,45.9838652],[17.3041996,46.0021128],[17.2579726,46.0110256],[17.29632,46.0285169],[17.2541514,46.030005],[17.270955,46.0567055],[17.2324767,46.0592034],[17.2525145,46.0664725],[17.2313144,46.0790345],[17.2019916,46.0765488],[17.2331299,46.0989644],[17.2104017,46.1001693],[17.2129734,46.113855],[17.175927,46.1084583],[17.1743424,46.1287608],[17.1865197,46.1332308],[17.1810983,46.1505485],[17.1562307,46.1585819],[17.1592857,46.1696818],[17.1261012,46.1684495],[17.1227409,46.1789791],[17.0752482,46.1889531],[17.0661614,46.2022984],[16.9735401,46.2251982],[16.973954,46.2431113],[16.9504085,46.2415285],[16.8862356,46.2814598],[16.8713682,46.3252767],[16.8802109,46.3356966],[16.8615374,46.3452401],[16.8656232,46.3556489],[16.8521959,46.3517189],[16.8498589,46.3626245],[16.8352859,46.3638195],[16.8376499,46.3748032],[16.8261732,46.3670994],[16.7933444,46.387385],[16.7592072,46.3776563],[16.7298672,46.40149],[16.7182119,46.3898704],[16.6772872,46.4494536],[16.6631785,46.4486958],[16.6663732,46.4582995],[16.6187915,46.4619875],[16.604468,46.4760773],[16.5235997,46.5053761],[16.5325768,46.5314027],[16.5176728,46.5363516],[16.5084107,46.5652692],[16.4829969,46.5660383],[16.4834008,46.5786011],[16.4455713,46.610952],[16.4248583,46.6131645],[16.385941,46.6442485],[16.3915424,46.6637257],[16.4198454,46.6584771],[16.4286335,46.6939737],[16.3689211,46.7040082],[16.3798266,46.7153869],[16.3710856,46.7222945],[16.3570587,46.7142387],[16.3185954,46.7541449],[16.3305417,46.7752119],[16.3121626,46.7780033],[16.3127666,46.797314],[16.3406373,46.8051851],[16.3508404,46.8300552],[16.3403309,46.8468762],[16.3015007,46.8595142],[16.2913867,46.8728341],[16.2332296,46.8766702],[16.1560866,46.8537074],[16.126571,46.8569079],[16.1139147,46.8691038]]],"terms_url":"http://www.fomi.hu/","terms_text":"Földmérési és Távérzékelési Intézet"},{"name":"FÖMI ortofotó 2005","type":"tms","description":"Hungary","template":"http://e.tile.openstreetmap.hu/ortofoto2005/{zoom}/{x}/{y}.jpg","scaleExtent":[0,17],"polygon":[[[16.1139147,46.8691038],[16.1789749,46.90662],[16.2000429,46.9415079],[16.2217547,46.9355441],[16.2462784,46.9463851],[16.2553226,46.9642125],[16.2764694,46.9626082],[16.290583,47.0139849],[16.3016199,46.9992329],[16.3414618,46.9965225],[16.3505162,47.0106313],[16.3734016,46.9985929],[16.412765,47.00475],[16.4332705,46.9927417],[16.4478119,47.003893],[16.479997,46.9941169],[16.5121988,47.0011695],[16.4635584,47.0322699],[16.4478586,47.0227481],[16.439123,47.029663],[16.445673,47.038872],[16.520323,47.056103],[16.473213,47.0736169],[16.4637199,47.09392],[16.500798,47.110058],[16.500035,47.123295],[16.5295349,47.1287419],[16.5171609,47.1496938],[16.454951,47.1425878],[16.4648728,47.1683349],[16.4555643,47.1875584],[16.4305559,47.1847022],[16.4195013,47.1949147],[16.4189215,47.2107114],[16.4371293,47.2097043],[16.4426335,47.2337117],[16.4313127,47.2527554],[16.4671512,47.2531652],[16.4892319,47.2798885],[16.4646338,47.3338455],[16.4337002,47.3528101],[16.458513,47.3670496],[16.4454619,47.4070195],[16.4831657,47.4093628],[16.4963821,47.3892659],[16.5170941,47.4100218],[16.5749054,47.4054243],[16.5807291,47.4191699],[16.661847,47.455595],[16.6706419,47.47422],[16.6523395,47.500342],[16.6895619,47.510161],[16.7147797,47.540199],[16.663545,47.567733],[16.673199,47.6049544],[16.6595343,47.6061018],[16.652758,47.622852],[16.6314207,47.6283176],[16.5739108,47.619667],[16.5147382,47.6461964],[16.4967504,47.6393149],[16.425464,47.6621679],[16.4437449,47.674205],[16.4480507,47.6964725],[16.4746984,47.6811576],[16.4872245,47.6979767],[16.5521729,47.7225519],[16.5363779,47.736785],[16.5479799,47.751544],[16.6095193,47.7603722],[16.6344148,47.7590843],[16.65729,47.7414879],[16.7209405,47.7353565],[16.7534062,47.6828165],[16.8301587,47.681058],[16.8394284,47.7045139],[16.8668943,47.7211462],[16.876679,47.6876452],[17.0937421,47.7077706],[17.0706562,47.7285366],[17.0516019,47.7938499],[17.0749479,47.8084997],[17.047139,47.8285635],[17.0519452,47.8377691],[17.0105513,47.8581765],[17.0163878,47.8673325],[17.0857537,47.8746239],[17.113171,47.9271605],[17.0917133,47.9342916],[17.1183782,47.9601083],[17.094657,47.9708775],[17.2010289,48.019992],[17.241769,48.0224651],[17.257955,47.998655],[17.334651,47.993125],[17.4029929,47.947849],[17.4539199,47.8852579],[17.5267369,47.865509],[17.5675779,47.8151289],[17.608402,47.8218859],[17.7085789,47.756678],[17.7798739,47.739487],[17.8660959,47.74575],[17.9001292,47.7392633],[17.946867,47.744668],[17.9708709,47.7578392],[18.0044103,47.7463402],[18.0380583,47.7576812],[18.2958774,47.7314616],[18.4540681,47.7651226],[18.4931553,47.7527552],[18.5590761,47.7659963],[18.6460866,47.7590921],[18.7260691,47.7890411],[18.7411784,47.8138245],[18.7920013,47.8230869],[18.8485417,47.8167221],[18.855876,47.826077],[18.828014,47.834291],[18.8135749,47.85555],[18.76353,47.8716049],[18.756858,47.896838],[18.776746,47.955092],[18.7552499,47.9763469],[18.8157429,47.993442],[18.819998,48.039676],[18.833268,48.048239],[18.8749364,48.0470707],[18.886674,48.058682],[18.9089819,48.051139],[18.9439039,48.058865],[18.9816099,48.0536009],[19.0148639,48.078179],[19.0585249,48.0573529],[19.0843619,48.072781],[19.107402,48.065596],[19.1352889,48.074146],[19.2413679,48.0536529],[19.2557819,48.0715559],[19.3031119,48.088711],[19.3865969,48.091914],[19.400018,48.082304],[19.454053,48.101436],[19.467354,48.083933],[19.4944199,48.109906],[19.492377,48.1396639],[19.5128219,48.154663],[19.504518,48.173443],[19.528967,48.190358],[19.526044,48.20313],[19.577502,48.2160149],[19.6308263,48.2500725],[19.6445239,48.2391719],[19.669857,48.239212],[19.691219,48.203894],[19.721125,48.201473],[19.74618,48.2165119],[19.7871629,48.19253],[19.7987329,48.19482],[19.8052829,48.183733],[19.782415,48.165039],[19.794812,48.153529],[19.821331,48.169081],[19.8452819,48.162742],[19.8551729,48.178431],[19.8601309,48.169409],[19.898745,48.1663119],[19.9145359,48.146863],[19.898298,48.1249019],[19.937383,48.131118],[19.9743939,48.1660049],[19.988706,48.1621679],[20.029038,48.1776849],[20.049449,48.1671999],[20.0729859,48.179606],[20.0700369,48.1917019],[20.1340909,48.225182],[20.1331879,48.253982],[20.206162,48.250979],[20.2038299,48.261906],[20.228466,48.262779],[20.2349469,48.279933],[20.286858,48.26164],[20.3257109,48.272794],[20.3374649,48.301667],[20.3656579,48.316606],[20.384077,48.3511809],[20.4098349,48.365857],[20.402532,48.382565],[20.4205349,48.403858],[20.416228,48.418536],[20.507929,48.489363],[20.5065069,48.534415],[20.537471,48.527878],[20.5464939,48.544292],[20.586595,48.535759],[20.6538739,48.561413],[20.836359,48.58284],[20.8378,48.57421],[20.8504359,48.5816329],[20.8453301,48.5665046],[20.8681549,48.551818],[20.922323,48.559453],[20.9346349,48.538341],[20.955882,48.533963],[20.9561979,48.521666],[20.9815849,48.5177669],[21.0151139,48.532313],[21.0663209,48.525894],[21.1174479,48.4910549],[21.1608749,48.521499],[21.179634,48.518232],[21.221061,48.537497],[21.305488,48.5222489],[21.313377,48.550841],[21.326875,48.554129],[21.319384,48.561201],[21.4154499,48.558951],[21.4226649,48.578821],[21.4406099,48.585104],[21.514091,48.551065],[21.5420199,48.508395],[21.6139329,48.509416],[21.6201879,48.469826],[21.663549,48.417961],[21.6645609,48.392164],[21.7017409,48.380695],[21.711871,48.357617],[21.8174139,48.332787],[21.8352029,48.3346409],[21.837213,48.363253],[21.8842979,48.356047],[21.8848429,48.367539],[21.897883,48.36256],[21.8997959,48.3702229],[21.9281859,48.3615969],[21.9268059,48.370899],[21.949198,48.378728],[21.994463,48.377323],[22.0213259,48.392749],[22.0546049,48.377528],[22.0764859,48.387241],[22.086743,48.371564],[22.1359089,48.380519],[22.131056,48.3912329],[22.152768,48.3962409],[22.1561913,48.4093076],[22.2125722,48.4256468],[22.2371405,48.4100396],[22.2654858,48.4098675],[22.2398761,48.3870055],[22.2675722,48.3611612],[22.3178106,48.3545437],[22.3132861,48.3250712],[22.3372944,48.3079113],[22.3384267,48.2792074],[22.3847547,48.2339632],[22.4006407,48.249198],[22.4328384,48.2525166],[22.456386,48.2423109],[22.4899029,48.2534237],[22.4972201,48.2395546],[22.5161491,48.237965],[22.5311088,48.2094282],[22.5711442,48.1961428],[22.5616362,48.1816066],[22.5982449,48.144756],[22.5902763,48.1073414],[22.6754492,48.091997],[22.7347192,48.119848],[22.7576242,48.1200599],[22.7703914,48.1090162],[22.772319,48.1218742],[22.8027688,48.1221112],[22.8025285,48.1070813],[22.8254256,48.1175119],[22.8364365,48.080249],[22.8611284,48.0750312],[22.8677955,48.0524256],[22.8820424,48.0548053],[22.8659692,48.0113165],[22.835562,47.9905988],[22.8407599,47.9813636],[22.8725729,47.9752683],[22.8697274,47.9659593],[22.8915652,47.9672446],[22.897435,47.9540629],[22.8473299,47.9077579],[22.7928135,47.8908586],[22.7586924,47.8941446],[22.77775,47.8422508],[22.7136344,47.8360928],[22.6801938,47.7877527],[22.6111171,47.7717455],[22.5490018,47.7722246],[22.4812121,47.8108886],[22.4513078,47.803389],[22.4313319,47.7398119],[22.3566167,47.7486206],[22.3177714,47.7660887],[22.3176236,47.7433657],[22.2851369,47.7292757],[22.264325,47.7310675],[22.2589955,47.6979057],[22.2306796,47.693196],[22.1796501,47.5916115],[22.1289245,47.5978984],[22.0942787,47.5583628],[22.0782587,47.5621299],[22.0534529,47.5474795],[22.0712176,47.5380742],[22.0617872,47.5288029],[22.0451278,47.5398919],[22.0367222,47.5326653],[22.0071886,47.48362],[22.0327909,47.4508372],[22.0238835,47.3908631],[22.0119849,47.3758016],[21.9627373,47.381053],[21.9382461,47.3725317],[21.8777922,47.2857763],[21.8872845,47.2730473],[21.8534909,47.2397622],[21.8580662,47.1873597],[21.8124804,47.1667511],[21.7924092,47.1059751],[21.7268258,47.0983882],[21.6976037,47.057915],[21.6504151,47.0408303],[21.6888701,47.0019977],[21.6678744,46.9712337],[21.6814917,46.9652089],[21.6381964,46.9330487],[21.5984455,46.9274708],[21.6142857,46.8867275],[21.6016694,46.8668202],[21.520328,46.8373749],[21.5186086,46.8000703],[21.4831761,46.7650246],[21.5263389,46.7393249],[21.529369,46.7209721],[21.4923253,46.6859652],[21.4728438,46.6959075],[21.4299047,46.693937],[21.4309553,46.6781367],[21.4546661,46.660863],[21.4162375,46.6426231],[21.4097959,46.6218052],[21.3657038,46.6379501],[21.3300499,46.6318155],[21.3139733,46.617666],[21.3012351,46.5908672],[21.3207905,46.5828562],[21.2743045,46.5407362],[21.2600254,46.5021583],[21.2744188,46.4767333],[21.2964506,46.4762973],[21.3174343,46.4507288],[21.2895176,46.4154784],[21.2963256,46.4069601],[21.2250116,46.4136899],[21.2064214,46.4033825],[21.1992563,46.3479034],[21.1762269,46.3357664],[21.180497,46.3044494],[21.1155437,46.3018529],[21.1030549,46.2624637],[21.0708792,46.2539014],[21.0660827,46.2429394],[21.0366237,46.2480392],[21.0246723,46.2665329],[20.960817,46.2623039],[20.9465849,46.2793024],[20.9250701,46.2766191],[20.9218133,46.2618129],[20.8732713,46.2877555],[20.7756538,46.2759602],[20.7490474,46.2508489],[20.7618619,46.204563],[20.727401,46.2077485],[20.7341052,46.1939355],[20.7140487,46.1660531],[20.6843592,46.1447802],[20.6549178,46.1497739],[20.6394471,46.1267602],[20.5450486,46.1790935],[20.5014839,46.190334],[20.4949436,46.1709908],[20.4592293,46.1428837],[20.3975133,46.1574709],[20.3685325,46.1528554],[20.3557074,46.1696256],[20.2968136,46.1521542],[20.2549024,46.1158522],[20.2484757,46.1300956],[20.2330132,46.1241668],[20.1817362,46.1601137],[20.1364966,46.1449476],[20.1009667,46.1772756],[20.0636156,46.1437275],[20.0346142,46.1458888],[20.0158072,46.1768354],[19.9354075,46.1764243],[19.8533469,46.1500005],[19.8179747,46.1281652],[19.7585403,46.1479754],[19.6982054,46.1879317],[19.6827672,46.1800388],[19.661508,46.1904394],[19.6317396,46.1692993],[19.5676482,46.179106],[19.5604013,46.1665762],[19.5026585,46.1424492],[19.5271208,46.1210269],[19.4645033,46.0953827],[19.4665828,46.0820437],[19.4160037,46.0460453],[19.3803957,46.0358749],[19.3640923,46.0522965],[19.2819012,46.0148048],[19.2965348,45.9881173],[19.2856472,45.9968981],[19.1479857,45.9963445],[19.1338422,46.0370993],[19.104873,46.0401673],[19.0660427,46.0001999],[19.0796791,45.9636376],[19.0059803,45.9590674],[19.0092745,45.9236559],[18.9061334,45.9353801],[18.8794572,45.9166827],[18.8647137,45.9208493],[18.8685629,45.9113361],[18.8276792,45.9051714],[18.8220041,45.9145893],[18.8075092,45.9036055],[18.809247,45.8796189],[18.7956242,45.8784488],[18.7048857,45.9181883],[18.6700246,45.9108439],[18.6596602,45.9168934],[18.6651348,45.899279],[18.6412808,45.8890396],[18.6550179,45.8742393],[18.6277704,45.8733782],[18.6148449,45.8531438],[18.6236656,45.8398531],[18.5732391,45.8137578],[18.5749849,45.8004344],[18.559716,45.8037961],[18.5223504,45.7826858],[18.4906706,45.7947167],[18.4821905,45.7655032],[18.4562828,45.7695229],[18.4450763,45.7605195],[18.446853,45.737128],[18.40763,45.7397119],[18.3918949,45.7616983],[18.3642257,45.7729364],[18.3394214,45.7471605],[18.2968157,45.7612196],[18.2440473,45.7612305],[18.2307311,45.7790328],[18.1908702,45.7878759],[18.1681939,45.7762712],[18.1246514,45.7896277],[18.1068067,45.7708256],[18.0818922,45.7645205],[17.9958808,45.7957311],[17.9302095,45.7863301],[17.9066757,45.7925692],[17.8653145,45.7670064],[17.8262748,45.8099957],[17.8089784,45.8040989],[17.7809054,45.8174884],[17.7603399,45.811923],[17.7408624,45.8295975],[17.6632915,45.8381849],[17.6276211,45.8979446],[17.5700676,45.9358204],[17.4378254,45.9503823],[17.4258964,45.9272681],[17.4108059,45.9399665],[17.392149,45.9302149],[17.3828713,45.9475733],[17.3476208,45.9423413],[17.3438769,45.9605329],[17.3537711,45.9525011],[17.3905375,45.9581914],[17.387423,45.9661823],[17.3583539,45.9642737],[17.3754852,45.9686921],[17.3751895,45.9881054],[17.3635685,45.9915442],[17.3567202,45.9735836],[17.3339583,45.9960781],[17.3319847,45.9728948],[17.3129974,45.9665347],[17.323647,45.9887776],[17.2987653,45.9838652],[17.3041996,46.0021128],[17.2579726,46.0110256],[17.29632,46.0285169],[17.2541514,46.030005],[17.270955,46.0567055],[17.2324767,46.0592034],[17.2525145,46.0664725],[17.2313144,46.0790345],[17.2019916,46.0765488],[17.2331299,46.0989644],[17.2104017,46.1001693],[17.2129734,46.113855],[17.175927,46.1084583],[17.1743424,46.1287608],[17.1865197,46.1332308],[17.1810983,46.1505485],[17.1562307,46.1585819],[17.1592857,46.1696818],[17.1261012,46.1684495],[17.1227409,46.1789791],[17.0752482,46.1889531],[17.0661614,46.2022984],[16.9735401,46.2251982],[16.973954,46.2431113],[16.9504085,46.2415285],[16.8862356,46.2814598],[16.8713682,46.3252767],[16.8802109,46.3356966],[16.8615374,46.3452401],[16.8656232,46.3556489],[16.8521959,46.3517189],[16.8498589,46.3626245],[16.8352859,46.3638195],[16.8376499,46.3748032],[16.8261732,46.3670994],[16.7933444,46.387385],[16.7592072,46.3776563],[16.7298672,46.40149],[16.7182119,46.3898704],[16.6772872,46.4494536],[16.6631785,46.4486958],[16.6663732,46.4582995],[16.6187915,46.4619875],[16.604468,46.4760773],[16.5235997,46.5053761],[16.5325768,46.5314027],[16.5176728,46.5363516],[16.5084107,46.5652692],[16.4829969,46.5660383],[16.4834008,46.5786011],[16.4455713,46.610952],[16.4248583,46.6131645],[16.385941,46.6442485],[16.3915424,46.6637257],[16.4198454,46.6584771],[16.4286335,46.6939737],[16.3689211,46.7040082],[16.3798266,46.7153869],[16.3710856,46.7222945],[16.3570587,46.7142387],[16.3185954,46.7541449],[16.3305417,46.7752119],[16.3121626,46.7780033],[16.3127666,46.797314],[16.3406373,46.8051851],[16.3508404,46.8300552],[16.3403309,46.8468762],[16.3015007,46.8595142],[16.2913867,46.8728341],[16.2332296,46.8766702],[16.1560866,46.8537074],[16.126571,46.8569079],[16.1139147,46.8691038]]],"terms_url":"http://www.fomi.hu/","terms_text":"Földmérési és Távérzékelési Intézet"},{"name":"FR-BAN","type":"tms","description":"French address registry or Base Adresses Nationale","template":"http://{switch:a,b,c}.layers.openstreetmap.fr/bano/{zoom}/{x}/{y}.png","scaleExtent":[12,20],"polygon":[[[8.3247852,49.0891892],[6.1566882,49.6167369],[4.8666714,50.2126152],[2.4937064,51.1761675],[1.3121526,50.9324682],[1.2659981,50.1877492],[0.1121369,49.8258592],[-0.3494075,49.4312336],[-1.0232625,49.4852345],[-1.3278818,49.7901162],[-2.1032765,49.7901162],[-1.6232703,48.7420657],[-3.1002126,48.9728514],[-5.1125465,48.6811558],[-5.3525496,48.4367783],[-4.5984193,47.7194959],[-2.555398,47.0232784],[-2.4738077,46.6638823],[-1.6676954,46.1055717],[-1.334807,45.5141125],[-1.4914604,44.1627003],[-1.9940567,43.3708146],[-0.956228,42.7364747],[2.2029487,42.2841894],[3.2342502,42.5444129],[3.2407774,43.1140543],[4.0436261,43.3280964],[6.4325902,42.808345],[7.6270723,43.5934102],[7.8163619,44.1720643],[7.0396221,44.41967],[7.268075,45.4958141],[7.1244761,46.2140775],[6.5631347,46.771283],[7.6571492,47.59128],[7.6527839,47.5941813],[7.6224698,47.5776739],[7.6047297,47.578221],[7.5877054,47.5901532],[7.521558,47.65161],[7.503992,47.70235],[7.520958,47.77685],[7.557124,47.84839],[7.549463,47.879205],[7.574615,47.93028],[7.613179,47.96804],[7.611904,47.9871],[7.5612401,48.0383618],[7.574915,48.1258],[7.595338,48.15977],[7.633047,48.19717],[7.662748,48.22473],[7.684659,48.30305],[7.763463,48.49158],[7.8004602,48.5125977],[7.799582,48.5878],[7.834088,48.64439],[7.9121073,48.6889897],[7.9672295,48.7571585],[8.020692,48.78879],[8.043024,48.7956],[8.0864658,48.8130551],[8.1364418,48.8978239],[8.1970586,48.96021],[8.2816129,48.9948995],[8.2996723,49.025966],[8.3124269,49.0599642],[8.3247852,49.0891892]],[[9.3609615,43.1345098],[8.4393174,42.48439],[8.4836272,41.8175373],[8.8469677,41.3768281],[9.2058772,41.3136241],[9.48946,41.5461776],[9.6356823,42.1994563],[9.6046655,42.901254],[9.3609615,43.1345098]]],"terms_url":"https://wiki.openstreetmap.org/wiki/WikiProject_France/WikiProject_Base_Adresses_Nationale_Ouverte_(BANO)","terms_text":"Tiles © cquest@Openstreetmap France, data © OpenStreetMap contributors, ODBL","id":"FR-BAN"},{"name":"FR-Cadastre","type":"tms","description":"French land registry","template":"http://tms.cadastre.openstreetmap.fr/*/tout/{z}/{x}/{y}.png","scaleExtent":[12,20],"polygon":[[[8.3247852,49.0891892],[6.1566882,49.6167369],[4.8666714,50.2126152],[2.4937064,51.1761675],[1.3121526,50.9324682],[1.2659981,50.1877492],[0.1121369,49.8258592],[-0.3494075,49.4312336],[-1.0232625,49.4852345],[-1.3278818,49.7901162],[-2.1032765,49.7901162],[-1.6232703,48.7420657],[-3.1002126,48.9728514],[-5.1125465,48.6811558],[-5.3525496,48.4367783],[-4.5984193,47.7194959],[-2.555398,47.0232784],[-2.4738077,46.6638823],[-1.6676954,46.1055717],[-1.334807,45.5141125],[-1.4914604,44.1627003],[-1.9940567,43.3708146],[-0.956228,42.7364747],[2.2029487,42.2841894],[3.2342502,42.5444129],[3.2407774,43.1140543],[4.0436261,43.3280964],[6.4325902,42.808345],[7.6270723,43.5934102],[7.8163619,44.1720643],[7.0396221,44.41967],[7.268075,45.4958141],[7.1244761,46.2140775],[6.5631347,46.771283],[7.6571492,47.59128],[7.6527839,47.5941813],[7.6224698,47.5776739],[7.6047297,47.578221],[7.5877054,47.5901532],[7.521558,47.65161],[7.503992,47.70235],[7.520958,47.77685],[7.557124,47.84839],[7.549463,47.879205],[7.574615,47.93028],[7.613179,47.96804],[7.611904,47.9871],[7.5612401,48.0383618],[7.574915,48.1258],[7.595338,48.15977],[7.633047,48.19717],[7.662748,48.22473],[7.684659,48.30305],[7.763463,48.49158],[7.8004602,48.5125977],[7.799582,48.5878],[7.834088,48.64439],[7.9121073,48.6889897],[7.9672295,48.7571585],[8.020692,48.78879],[8.043024,48.7956],[8.0864658,48.8130551],[8.1364418,48.8978239],[8.1970586,48.96021],[8.2816129,48.9948995],[8.2996723,49.025966],[8.3124269,49.0599642],[8.3247852,49.0891892]],[[9.3609615,43.1345098],[8.4393174,42.48439],[8.4836272,41.8175373],[8.8469677,41.3768281],[9.2058772,41.3136241],[9.48946,41.5461776],[9.6356823,42.1994563],[9.6046655,42.901254],[9.3609615,43.1345098]]],"terms_url":"http://wiki.openstreetmap.org/wiki/WikiProject_Cadastre_Fran%C3%A7ais/Conditions_d%27utilisation","terms_text":"cadastre-dgi-fr source : Direction Générale des Impôts - Cadastre. Mise à jour : 2015","id":"FR-Cadastre"},{"name":"Freemap.sk Car","type":"tms","template":"http://t{switch:1,2,3,4}.freemap.sk/A/{zoom}/{x}/{y}.jpeg","scaleExtent":[8,16],"polygon":[[[19.83682,49.25529],[19.80075,49.42385],[19.60437,49.48058],[19.49179,49.63961],[19.21831,49.52604],[19.16778,49.42521],[19.00308,49.42236],[18.97611,49.5308],[18.54685,49.51425],[18.31432,49.33818],[18.15913,49.2961],[18.05564,49.11134],[17.56396,48.84938],[17.17929,48.88816],[17.058,48.81105],[16.90426,48.61947],[16.79685,48.38561],[17.06762,48.01116],[17.32787,47.97749],[17.51699,47.82535],[17.74776,47.73093],[18.29515,47.72075],[18.67959,47.75541],[18.89755,47.81203],[18.79463,47.88245],[18.84318,48.04046],[19.46212,48.05333],[19.62064,48.22938],[19.89585,48.09387],[20.33766,48.2643],[20.55395,48.52358],[20.82335,48.55714],[21.10271,48.47096],[21.45863,48.55513],[21.74536,48.31435],[22.15293,48.37179],[22.61255,49.08914],[22.09997,49.23814],[21.9686,49.36363],[21.6244,49.46989],[21.06873,49.46402],[20.94336,49.31088],[20.73052,49.44006],[20.22804,49.41714],[20.05234,49.23052],[19.83682,49.25529]]],"terms_text":"Copyright ©2007-2012 Freemap Slovakia (www.freemap.sk). Some rights reserved."},{"name":"Freemap.sk Cyclo","type":"tms","template":"http://t{switch:1,2,3,4}.freemap.sk/C/{zoom}/{x}/{y}.jpeg","scaleExtent":[8,16],"polygon":[[[19.83682,49.25529],[19.80075,49.42385],[19.60437,49.48058],[19.49179,49.63961],[19.21831,49.52604],[19.16778,49.42521],[19.00308,49.42236],[18.97611,49.5308],[18.54685,49.51425],[18.31432,49.33818],[18.15913,49.2961],[18.05564,49.11134],[17.56396,48.84938],[17.17929,48.88816],[17.058,48.81105],[16.90426,48.61947],[16.79685,48.38561],[17.06762,48.01116],[17.32787,47.97749],[17.51699,47.82535],[17.74776,47.73093],[18.29515,47.72075],[18.67959,47.75541],[18.89755,47.81203],[18.79463,47.88245],[18.84318,48.04046],[19.46212,48.05333],[19.62064,48.22938],[19.89585,48.09387],[20.33766,48.2643],[20.55395,48.52358],[20.82335,48.55714],[21.10271,48.47096],[21.45863,48.55513],[21.74536,48.31435],[22.15293,48.37179],[22.61255,49.08914],[22.09997,49.23814],[21.9686,49.36363],[21.6244,49.46989],[21.06873,49.46402],[20.94336,49.31088],[20.73052,49.44006],[20.22804,49.41714],[20.05234,49.23052],[19.83682,49.25529]]],"terms_text":"Copyright ©2007-2012 Freemap Slovakia (www.freemap.sk). Some rights reserved."},{"name":"Freemap.sk Hiking","type":"tms","template":"http://t{switch:1,2,3,4}.freemap.sk/T/{zoom}/{x}/{y}.jpeg","scaleExtent":[8,16],"polygon":[[[19.83682,49.25529],[19.80075,49.42385],[19.60437,49.48058],[19.49179,49.63961],[19.21831,49.52604],[19.16778,49.42521],[19.00308,49.42236],[18.97611,49.5308],[18.54685,49.51425],[18.31432,49.33818],[18.15913,49.2961],[18.05564,49.11134],[17.56396,48.84938],[17.17929,48.88816],[17.058,48.81105],[16.90426,48.61947],[16.79685,48.38561],[17.06762,48.01116],[17.32787,47.97749],[17.51699,47.82535],[17.74776,47.73093],[18.29515,47.72075],[18.67959,47.75541],[18.89755,47.81203],[18.79463,47.88245],[18.84318,48.04046],[19.46212,48.05333],[19.62064,48.22938],[19.89585,48.09387],[20.33766,48.2643],[20.55395,48.52358],[20.82335,48.55714],[21.10271,48.47096],[21.45863,48.55513],[21.74536,48.31435],[22.15293,48.37179],[22.61255,49.08914],[22.09997,49.23814],[21.9686,49.36363],[21.6244,49.46989],[21.06873,49.46402],[20.94336,49.31088],[20.73052,49.44006],[20.22804,49.41714],[20.05234,49.23052],[19.83682,49.25529]]],"terms_text":"Copyright ©2007-2012 Freemap Slovakia (www.freemap.sk). Some rights reserved."},{"name":"Freemap.sk Ski","type":"tms","template":"http://t{switch:1,2,3,4}.freemap.sk/K/{zoom}/{x}/{y}.jpeg","scaleExtent":[8,16],"polygon":[[[19.83682,49.25529],[19.80075,49.42385],[19.60437,49.48058],[19.49179,49.63961],[19.21831,49.52604],[19.16778,49.42521],[19.00308,49.42236],[18.97611,49.5308],[18.54685,49.51425],[18.31432,49.33818],[18.15913,49.2961],[18.05564,49.11134],[17.56396,48.84938],[17.17929,48.88816],[17.058,48.81105],[16.90426,48.61947],[16.79685,48.38561],[17.06762,48.01116],[17.32787,47.97749],[17.51699,47.82535],[17.74776,47.73093],[18.29515,47.72075],[18.67959,47.75541],[18.89755,47.81203],[18.79463,47.88245],[18.84318,48.04046],[19.46212,48.05333],[19.62064,48.22938],[19.89585,48.09387],[20.33766,48.2643],[20.55395,48.52358],[20.82335,48.55714],[21.10271,48.47096],[21.45863,48.55513],[21.74536,48.31435],[22.15293,48.37179],[22.61255,49.08914],[22.09997,49.23814],[21.9686,49.36363],[21.6244,49.46989],[21.06873,49.46402],[20.94336,49.31088],[20.73052,49.44006],[20.22804,49.41714],[20.05234,49.23052],[19.83682,49.25529]]],"terms_text":"Copyright ©2007-2012 Freemap Slovakia (www.freemap.sk). Some rights reserved."},{"name":"Geodatastyrelsen (Denmark)","type":"tms","template":"http://osmtools.septima.dk/mapproxy/tiles/1.0.0/kortforsyningen_ortoforaar/EPSG3857/{zoom}/{x}/{y}.jpeg","scaleExtent":[0,21],"polygon":[[[8.3743941,54.9551655],[8.3683809,55.4042149],[8.2103997,55.4039795],[8.2087314,55.4937345],[8.0502655,55.4924731],[8.0185123,56.7501399],[8.1819161,56.7509948],[8.1763274,57.0208898],[8.3413329,57.0219872],[8.3392467,57.1119574],[8.5054433,57.1123212],[8.5033923,57.2020499],[9.3316304,57.2027636],[9.3319079,57.2924835],[9.4978864,57.2919578],[9.4988593,57.3820608],[9.6649749,57.3811615],[9.6687295,57.5605591],[9.8351961,57.5596265],[9.8374896,57.6493322],[10.1725726,57.6462818],[10.1754245,57.7367768],[10.5118282,57.7330269],[10.5152095,57.8228945],[10.6834853,57.8207722],[10.6751613,57.6412021],[10.5077045,57.6433097],[10.5039992,57.5535088],[10.671038,57.5514113],[10.6507805,57.1024538],[10.4857673,57.1045138],[10.4786236,56.9249051],[10.3143981,56.9267573],[10.3112341,56.8369269],[10.4750295,56.83509],[10.4649016,56.5656681],[10.9524239,56.5589761],[10.9479249,56.4692243],[11.1099335,56.4664675],[11.1052639,56.376833],[10.9429901,56.3795284],[10.9341235,56.1994768],[10.7719685,56.2020244],[10.7694751,56.1120103],[10.6079695,56.1150259],[10.4466742,56.116717],[10.2865948,56.118675],[10.2831527,56.0281851],[10.4439274,56.0270388],[10.4417713,55.7579243],[10.4334961,55.6693533],[10.743814,55.6646861],[10.743814,55.5712253],[10.8969041,55.5712253],[10.9051793,55.3953852],[11.0613726,55.3812841],[11.0593038,55.1124061],[11.0458567,55.0318621],[11.2030844,55.0247474],[11.2030844,55.117139],[11.0593038,55.1124061],[11.0613726,55.3812841],[11.0789572,55.5712253],[10.8969041,55.5712253],[10.9258671,55.6670198],[10.743814,55.6646861],[10.7562267,55.7579243],[10.4417713,55.7579243],[10.4439274,56.0270388],[10.4466742,56.116717],[10.6079695,56.1150259],[10.6052053,56.0247462],[10.9258671,56.0201215],[10.9197132,55.9309388],[11.0802782,55.92792],[11.0858066,56.0178284],[11.7265047,56.005058],[11.7319981,56.0952142],[12.0540333,56.0871256],[12.0608477,56.1762576],[12.7023469,56.1594405],[12.6611131,55.7114318],[12.9792318,55.7014026],[12.9612912,55.5217294],[12.3268659,55.5412096],[12.3206071,55.4513655],[12.4778226,55.447067],[12.4702432,55.3570479],[12.6269738,55.3523837],[12.6200898,55.2632576],[12.4627339,55.26722],[12.4552949,55.1778223],[12.2987046,55.1822303],[12.2897344,55.0923641],[12.6048608,55.0832904],[12.5872011,54.9036285],[12.2766618,54.9119031],[12.2610181,54.7331602],[12.1070691,54.7378161],[12.0858621,54.4681655],[11.7794953,54.4753579],[11.7837381,54.5654783],[11.1658525,54.5782155],[11.1706443,54.6686508],[10.8617173,54.6733956],[10.8651245,54.7634667],[10.7713646,54.7643888],[10.7707276,54.7372807],[10.7551428,54.7375776],[10.7544039,54.7195666],[10.7389074,54.7197588],[10.7384368,54.7108482],[10.7074486,54.7113045],[10.7041094,54.6756741],[10.5510973,54.6781698],[10.5547184,54.7670245],[10.2423994,54.7705935],[10.2459845,54.8604673],[10.0902268,54.8622134],[10.0873731,54.7723851],[9.1555798,54.7769557],[9.1562752,54.8675369],[8.5321973,54.8663765],[8.531432,54.95516],[8.3743941,54.9551655]],[[11.4577738,56.819554],[11.7849181,56.8127385],[11.7716715,56.6332796],[11.4459621,56.6401087],[11.4577738,56.819554]],[[11.3274736,57.3612962],[11.3161808,57.1818004],[11.1508692,57.1847276],[11.1456628,57.094962],[10.8157703,57.1001693],[10.8290599,57.3695272],[11.3274736,57.3612962]],[[11.5843266,56.2777928],[11.5782882,56.1880397],[11.7392309,56.1845765],[11.7456428,56.2743186],[11.5843266,56.2777928]],[[14.6825922,55.3639405],[14.8395247,55.3565231],[14.8263755,55.2671261],[15.1393406,55.2517359],[15.1532015,55.3410836],[15.309925,55.3330556],[15.295719,55.2437356],[15.1393406,55.2517359],[15.1255631,55.1623802],[15.2815819,55.1544167],[15.2535578,54.9757646],[14.6317464,55.0062496],[14.6825922,55.3639405]]],"terms_url":"http://download.kortforsyningen.dk/content/vilkaar-og-betingelser","terms_text":"Geodatastyrelsen og Danske Kommuner","best":true},{"name":"Geoportal.gov.pl (Orthophotomap)","type":"tms","template":"http://wms.misek.pl/geoportal.orto/tms/{zoom}/{x}/{y}","scaleExtent":[6,24],"polygon":[[[15.9751041,54.3709213],[16.311164,54.5561775],[17.1391878,54.7845723],[18.3448458,54.9022727],[19.6613689,54.4737213],[20.2815206,54.4213456],[21.4663914,54.3406369],[22.7759855,54.3769755],[22.8625989,54.4233613],[23.2956657,54.2678633],[23.5347186,54.0955258],[23.5208604,53.9775182],[23.7183389,53.4629603],[23.9296755,53.1856735],[23.9296755,52.6887269],[23.732197,52.6067497],[23.5658994,52.5878101],[23.2090523,52.3302642],[23.1951942,52.2370089],[23.5035377,52.1860596],[23.6906226,52.0030113],[23.5970802,51.739903],[23.6629063,51.3888562],[23.9366046,50.9827781],[24.1687284,50.8604752],[24.0197534,50.8035823],[24.1098313,50.6610467],[24.0578633,50.4188439],[23.6178674,50.3083403],[22.6824431,49.5163532],[22.7378756,49.2094935],[22.9041733,49.0780441],[22.8625989,48.9940062],[22.6096878,49.0371785],[22.0761495,49.2004392],[21.8474902,49.3721872],[21.3763135,49.4488281],[21.1026153,49.3721872],[20.9120659,49.3022043],[20.6452967,49.3902311],[20.1845136,49.3315641],[20.1186875,49.2004392],[19.9419962,49.1302123],[19.765305,49.2117568],[19.7479823,49.3992506],[19.6024718,49.4150307],[19.5089294,49.5815389],[19.4292451,49.5905232],[19.2317666,49.4150307],[18.9961783,49.387976],[18.9338167,49.4916048],[18.8368097,49.4938552],[18.8021643,49.6623381],[18.6427958,49.7094091],[18.521537,49.8994693],[18.0815412,50.0109209],[17.8875272,49.9886512],[17.7385522,50.0687739],[17.6068999,50.1709584],[17.7454813,50.2153184],[17.710836,50.3017019],[17.4163505,50.2640668],[16.9486384,50.4453265],[16.8932058,50.4033889],[17.0006064,50.3105529],[17.017929,50.2241854],[16.8135215,50.186489],[16.6402948,50.0976742],[16.4324227,50.2862087],[16.1968344,50.4276731],[16.4220291,50.5885165],[16.3388803,50.6632429],[16.2280152,50.6368824],[16.0547884,50.6127057],[15.5732181,50.7641544],[15.2683391,50.8976368],[15.2440873,50.980597],[15.0292862,51.0133036],[15.0015699,50.8582883],[14.8110205,50.8735944],[14.956531,51.0721176],[15.0188926,51.2914636],[14.9392083,51.4601459],[14.7209426,51.5571799],[14.7521234,51.6260562],[14.5996839,51.8427626],[14.70362,52.0733396],[14.5581095,52.2497371],[14.5165351,52.425436],[14.6031485,52.5878101],[14.1146491,52.8208272],[14.152759,52.9733951],[14.3502374,53.0734212],[14.4229927,53.2665624],[14.1977979,53.8734759],[14.2220497,53.9958517],[15.9751041,54.3709213]]],"terms_text":"Copyright © Główny Urząd Geodezji i Kartografii.","best":true},{"name":"IBGE Distrito Federal","type":"tms","description":"Addresses data from IBGE","template":"https://api.mapbox.com/styles/v1/wille/cirnnxni1000jg8nfppc8g7pm/tiles/256/{z}/{x}/{y}?access_token=pk.eyJ1Ijoid2lsbGUiLCJhIjoicFNVWk5VWSJ9.hluCd0YGvYHNlFi_utWe2g","scaleExtent":[0,19],"polygon":[[[-48.2444,-16.0508],[-48.2444,-15.5005],[-47.5695,-15.5005],[-47.5695,-16.0508],[-48.2444,-16.0508]]],"overlay":true},{"name":"IBGE Mapa de Setores Rurais","type":"tms","template":"http://{switch:a,b,c}.tiles.mapbox.com/v4/tmpsantos.i00mo1kj/{zoom}/{x}/{y}.png?access_token=pk.eyJ1Ijoib3BlbnN0cmVldG1hcCIsImEiOiJncjlmd0t3In0.DmZsIeOW-3x-C5eX-wAqTw","scaleExtent":[0,14],"polygon":[[[-29.3325,2.335959],[-28.72472,2.031551],[-27.76041,-8.937033],[-27.67249,-22.20839],[-51.11495,-35.46552],[-53.39394,-33.85064],[-53.62553,-33.72493],[-53.62503,-33.15428],[-53.24498,-32.73392],[-53.65747,-32.51873],[-53.8329,-32.16592],[-54.64174,-31.55507],[-55.29638,-31.3429],[-55.57371,-30.99691],[-56.06384,-31.16749],[-56.10468,-30.86436],[-56.86862,-30.20752],[-57.39671,-30.40464],[-57.74384,-30.22142],[-55.83724,-28.16598],[-54.86969,-27.44994],[-53.9016,-27.02998],[-53.74972,-26.25781],[-53.97158,-25.74513],[-54.44723,-25.79609],[-54.67802,-25.64668],[-54.36097,-24.35145],[-54.41679,-24.06527],[-54.64355,-23.94107],[-55.22163,-24.11355],[-55.49138,-24.02797],[-55.71734,-22.68488],[-55.90555,-22.39886],[-56.45255,-22.21731],[-56.8256,-22.4002],[-57.34109,-22.34351],[-58.08472,-22.13075],[-57.95766,-20.99818],[-58.26551,-20.24147],[-58.03577,-19.95871],[-58.23083,-19.75211],[-57.64739,-18.19828],[-57.89356,-17.57377],[-58.16997,-17.53519],[-58.48825,-17.21961],[-58.57691,-16.81466],[-58.45563,-16.42158],[-60.2541,-16.32571],[-60.33481,-15.51483],[-60.67423,-15.1122],[-60.34999,-14.99707],[-60.63603,-13.84119],[-61.07283,-13.62569],[-61.9025,-13.62647],[-62.21395,-13.25048],[-62.80185,-13.10905],[-63.17194,-12.76568],[-63.74229,-12.54071],[-64.32845,-12.59578],[-65.10261,-12.0682],[-65.45781,-11.27865],[-65.41641,-9.838943],[-66.52331,-9.985873],[-67.66452,-10.80093],[-67.99778,-10.75991],[-68.52286,-11.20807],[-69.88988,-11.02776],[-70.30957,-11.1699],[-70.71896,-11.02003],[-70.68128,-9.669083],[-71.27536,-10.08971],[-72.18053,-10.09967],[-72.41623,-9.587397],[-73.29207,-9.454149],[-73.0625,-9.017267],[-73.61432,-8.40982],[-74.09056,-7.527548],[-74.03652,-7.27885],[-73.84718,-7.238285],[-73.78618,-6.774872],[-73.22362,-6.430106],[-73.33719,-6.029736],[-72.93016,-5.038711],[-71.93973,-4.425027],[-70.96802,-4.248294],[-70.79598,-4.064931],[-70.02393,-4.167345],[-69.51025,-1.134089],[-69.70776,-0.567619],[-70.13645,-0.226161],[-70.14083,0.5844],[-69.26594,0.806502],[-69.34226,0.968924],[-69.92481,1.015705],[-69.92343,1.773851],[-68.38511,1.82943],[-68.24848,2.119808],[-67.94571,1.948424],[-67.37696,2.327468],[-67.05751,1.858336],[-67.00579,1.291603],[-66.79967,1.314684],[-66.28683,0.857709],[-65.67671,1.111146],[-65.42494,0.966549],[-65.15671,1.24203],[-64.27483,1.601591],[-64.0486,2.065137],[-63.47236,2.279358],[-64.13446,2.433909],[-64.10005,2.723778],[-64.32628,3.118275],[-64.28142,3.541983],[-64.88451,4.117671],[-64.88064,4.342461],[-64.13653,4.223152],[-63.95465,4.021316],[-63.17706,4.048301],[-62.96093,3.763658],[-62.82024,4.106019],[-62.49922,4.270815],[-61.91181,4.26284],[-61.35393,4.630097],[-61.04904,4.623115],[-60.70452,4.969851],[-60.78709,5.296764],[-60.22457,5.371207],[-59.89857,5.107541],[-59.97549,4.603025],[-59.59676,4.439875],[-59.41942,3.96994],[-59.71017,3.542008],[-59.88955,2.72301],[-59.63006,2.316332],[-59.63382,1.966581],[-59.18812,1.478079],[-58.80545,1.320732],[-58.35933,1.689932],[-57.6,1.803907],[-57.39854,2.065119],[-57.12392,2.128758],[-56.02925,1.949445],[-56.23884,2.263348],[-55.98195,2.628657],[-55.64816,2.519953],[-54.93958,2.682515],[-54.24988,2.25056],[-53.73937,2.473731],[-52.98578,2.280494],[-52.65712,2.564069],[-52.41739,3.22121],[-51.73983,4.119158],[-51.7246,4.556867],[-51.0112,5.522895],[-43.48209,5.335832],[-29.3325,2.335959]]]},{"name":"IBGE Mapa de Setores Urbanos","type":"tms","template":"http://{switch:a,b,c}.tiles.mapbox.com/v4/tmpsantos.hgda0m6h/{zoom}/{x}/{y}.png?access_token=pk.eyJ1Ijoib3BlbnN0cmVldG1hcCIsImEiOiJncjlmd0t3In0.DmZsIeOW-3x-C5eX-wAqTw","scaleExtent":[0,19],"polygon":[[[-29.3325,2.335959],[-28.72472,2.031551],[-27.76041,-8.937033],[-27.67249,-22.20839],[-51.11495,-35.46552],[-53.39394,-33.85064],[-53.62553,-33.72493],[-53.62503,-33.15428],[-53.24498,-32.73392],[-53.65747,-32.51873],[-53.8329,-32.16592],[-54.64174,-31.55507],[-55.29638,-31.3429],[-55.57371,-30.99691],[-56.06384,-31.16749],[-56.10468,-30.86436],[-56.86862,-30.20752],[-57.39671,-30.40464],[-57.74384,-30.22142],[-55.83724,-28.16598],[-54.86969,-27.44994],[-53.9016,-27.02998],[-53.74972,-26.25781],[-53.97158,-25.74513],[-54.44723,-25.79609],[-54.67802,-25.64668],[-54.36097,-24.35145],[-54.41679,-24.06527],[-54.64355,-23.94107],[-55.22163,-24.11355],[-55.49138,-24.02797],[-55.71734,-22.68488],[-55.90555,-22.39886],[-56.45255,-22.21731],[-56.8256,-22.4002],[-57.34109,-22.34351],[-58.08472,-22.13075],[-57.95766,-20.99818],[-58.26551,-20.24147],[-58.03577,-19.95871],[-58.23083,-19.75211],[-57.64739,-18.19828],[-57.89356,-17.57377],[-58.16997,-17.53519],[-58.48825,-17.21961],[-58.57691,-16.81466],[-58.45563,-16.42158],[-60.2541,-16.32571],[-60.33481,-15.51483],[-60.67423,-15.1122],[-60.34999,-14.99707],[-60.63603,-13.84119],[-61.07283,-13.62569],[-61.9025,-13.62647],[-62.21395,-13.25048],[-62.80185,-13.10905],[-63.17194,-12.76568],[-63.74229,-12.54071],[-64.32845,-12.59578],[-65.10261,-12.0682],[-65.45781,-11.27865],[-65.41641,-9.838943],[-66.52331,-9.985873],[-67.66452,-10.80093],[-67.99778,-10.75991],[-68.52286,-11.20807],[-69.88988,-11.02776],[-70.30957,-11.1699],[-70.71896,-11.02003],[-70.68128,-9.669083],[-71.27536,-10.08971],[-72.18053,-10.09967],[-72.41623,-9.587397],[-73.29207,-9.454149],[-73.0625,-9.017267],[-73.61432,-8.40982],[-74.09056,-7.527548],[-74.03652,-7.27885],[-73.84718,-7.238285],[-73.78618,-6.774872],[-73.22362,-6.430106],[-73.33719,-6.029736],[-72.93016,-5.038711],[-71.93973,-4.425027],[-70.96802,-4.248294],[-70.79598,-4.064931],[-70.02393,-4.167345],[-69.51025,-1.134089],[-69.70776,-0.567619],[-70.13645,-0.226161],[-70.14083,0.5844],[-69.26594,0.806502],[-69.34226,0.968924],[-69.92481,1.015705],[-69.92343,1.773851],[-68.38511,1.82943],[-68.24848,2.119808],[-67.94571,1.948424],[-67.37696,2.327468],[-67.05751,1.858336],[-67.00579,1.291603],[-66.79967,1.314684],[-66.28683,0.857709],[-65.67671,1.111146],[-65.42494,0.966549],[-65.15671,1.24203],[-64.27483,1.601591],[-64.0486,2.065137],[-63.47236,2.279358],[-64.13446,2.433909],[-64.10005,2.723778],[-64.32628,3.118275],[-64.28142,3.541983],[-64.88451,4.117671],[-64.88064,4.342461],[-64.13653,4.223152],[-63.95465,4.021316],[-63.17706,4.048301],[-62.96093,3.763658],[-62.82024,4.106019],[-62.49922,4.270815],[-61.91181,4.26284],[-61.35393,4.630097],[-61.04904,4.623115],[-60.70452,4.969851],[-60.78709,5.296764],[-60.22457,5.371207],[-59.89857,5.107541],[-59.97549,4.603025],[-59.59676,4.439875],[-59.41942,3.96994],[-59.71017,3.542008],[-59.88955,2.72301],[-59.63006,2.316332],[-59.63382,1.966581],[-59.18812,1.478079],[-58.80545,1.320732],[-58.35933,1.689932],[-57.6,1.803907],[-57.39854,2.065119],[-57.12392,2.128758],[-56.02925,1.949445],[-56.23884,2.263348],[-55.98195,2.628657],[-55.64816,2.519953],[-54.93958,2.682515],[-54.24988,2.25056],[-53.73937,2.473731],[-52.98578,2.280494],[-52.65712,2.564069],[-52.41739,3.22121],[-51.73983,4.119158],[-51.7246,4.556867],[-51.0112,5.522895],[-43.48209,5.335832],[-29.3325,2.335959]]]},{"name":"Imagerie Drone (Haiti)","type":"tms","template":"http://wms.openstreetmap.fr/tms/1.0.0/iomhaiti/{zoom}/{x}/{y}","polygon":[[[-72.1547401,19.6878969],[-72.162234,19.689011],[-72.164995,19.6932445],[-72.1657838,19.6979977],[-72.161603,19.7035677],[-72.1487449,19.7028993],[-72.1477194,19.7026765],[-72.1485082,19.7001514],[-72.1436963,19.7011169],[-72.1410143,19.7000029],[-72.139476,19.6973664],[-72.1382533,19.6927617],[-72.1386872,19.6923161],[-72.1380561,19.6896423],[-72.1385294,19.6894938],[-72.1388055,19.6901251],[-72.1388844,19.6876741],[-72.1378195,19.6872656],[-72.13778,19.6850003],[-72.1369517,19.6855945],[-72.136794,19.6840719],[-72.135729,19.6835148],[-72.1355713,19.6740817],[-72.1366362,19.6708133],[-72.1487843,19.6710733],[-72.1534779,19.6763843],[-72.1530835,19.6769414],[-72.1533251,19.6769768],[-72.1532807,19.6796525],[-72.1523834,19.6797175],[-72.1522749,19.6803488],[-72.1519101,19.6803395],[-72.1518608,19.6805067],[-72.1528173,19.6806552],[-72.1522299,19.6833011],[-72.1507801,19.6831499],[-72.1504457,19.6847862],[-72.1508591,19.6843492],[-72.1530087,19.6849898],[-72.1546258,19.6854354],[-72.1543103,19.6870694],[-72.1547244,19.6868466],[-72.1548501,19.6877564],[-72.1545814,19.6877982],[-72.1547401,19.6878969]],[[-72.1310601,19.6718929],[-72.1259842,19.6772765],[-72.1255379,19.6776179],[-72.1216891,19.6776442],[-72.1149677,19.672602],[-72.1152745,19.6687152],[-72.1198205,19.6627535],[-72.1227768,19.6625696],[-72.1248965,19.662701],[-72.1285779,19.6645394],[-72.1308091,19.6661677],[-72.1316737,19.668794],[-72.1315621,19.671],[-72.1310601,19.6718929]],[[-71.845795,19.6709758],[-71.8429354,19.6759525],[-71.8410027,19.6759525],[-71.8380249,19.6755254],[-71.8378671,19.6745041],[-71.8390504,19.6743927],[-71.8390109,19.6741141],[-71.8398392,19.673947],[-71.8389123,19.6736127],[-71.8380249,19.67209],[-71.8380052,19.6726285],[-71.8376699,19.6727214],[-71.8376305,19.672545],[-71.8354414,19.6732135],[-71.835333,19.6729999],[-71.8331242,19.6734642],[-71.8326706,19.6716815],[-71.8321579,19.67209],[-71.8307183,19.6694902],[-71.8306009,19.6697594],[-71.8302174,19.6698907],[-71.8291833,19.6672095],[-71.8290749,19.6672095],[-71.8289122,19.6667916],[-71.8289516,19.6666199],[-71.8288333,19.6663506],[-71.8285572,19.6664759],[-71.8288678,19.6672466],[-71.8287593,19.6674138],[-71.8277979,19.6678177],[-71.8277112,19.6678586],[-71.8278263,19.6679637],[-71.8271831,19.6681212],[-71.8271761,19.6680917],[-71.8264405,19.6683921],[-71.8264074,19.6683231],[-71.8261954,19.6684253],[-71.8261806,19.6683556],[-71.8258946,19.6684206],[-71.8258897,19.6686574],[-71.8251551,19.6687549],[-71.8254509,19.6691588],[-71.8229332,19.6695739],[-71.822713,19.6696658],[-71.8227688,19.6697577],[-71.8201751,19.6709855],[-71.8198474,19.6704537],[-71.8197985,19.6706014],[-71.8194674,19.6707557],[-71.8182472,19.6713433],[-71.8181426,19.6711431],[-71.8175813,19.6714254],[-71.816959,19.6707672],[-71.8176388,19.6718965],[-71.8171403,19.6720376],[-71.8158225,19.6718045],[-71.8138354,19.6711874],[-71.8123259,19.6706982],[-71.8121759,19.6704258],[-71.8124304,19.6701467],[-71.8119184,19.6700141],[-71.8118765,19.6705828],[-71.811169,19.6703483],[-71.8095938,19.6698516],[-71.8077992,19.6692829],[-71.8056028,19.668612],[-71.8051443,19.6668942],[-71.8051196,19.6652322],[-71.8052315,19.661979],[-71.8065603,19.6523921],[-71.8073412,19.6482946],[-71.8099686,19.6468292],[-71.8147517,19.6454502],[-71.8147726,19.6455619],[-71.8150027,19.6455093],[-71.8149469,19.6453846],[-71.8159928,19.6450234],[-71.8158882,19.6448855],[-71.8165854,19.6446097],[-71.8190119,19.643802],[-71.8211524,19.643454],[-71.8221564,19.6433292],[-71.8269046,19.643211],[-71.8280481,19.6432241],[-71.8304466,19.6440778],[-71.8306419,19.6448592],[-71.8295263,19.6450365],[-71.8296064,19.6456111],[-71.8299411,19.6455651],[-71.8303699,19.6451744],[-71.830471,19.6453452],[-71.8308092,19.6451974],[-71.8310184,19.6451088],[-71.8312519,19.6458541],[-71.8311125,19.6458245],[-71.831367,19.6465862],[-71.8328939,19.646189],[-71.8344566,19.6457062],[-71.8344664,19.6463052],[-71.834215,19.6461938],[-71.8342002,19.6465513],[-71.8346702,19.6463],[-71.8349118,19.6463905],[-71.8347984,19.6462187],[-71.8354393,19.6458496],[-71.8355034,19.6458032],[-71.8364747,19.6461328],[-71.8376382,19.6472658],[-71.8379143,19.647888],[-71.8390483,19.6508039],[-71.8456942,19.6696203],[-71.845795,19.6709758]],[[-72.098878,18.54843],[-72.096993,18.5501994],[-72.0972888,18.5503209],[-72.0968451,18.5503489],[-72.0955632,18.551854],[-72.0956428,18.5526742],[-72.0959914,18.5533748],[-72.0962145,18.553203],[-72.0962842,18.5535665],[-72.0964446,18.5535533],[-72.0965352,18.5539764],[-72.0965056,18.554173],[-72.0966085,18.5541747],[-72.0965178,18.5542127],[-72.0968769,18.5546588],[-72.0979018,18.5552141],[-72.1006211,18.5555875],[-72.1014926,18.5556206],[-72.1024339,18.5555016],[-72.103417,18.5543515],[-72.1034798,18.5516215],[-72.1030789,18.5516149],[-72.1033752,18.5515224],[-72.1035042,18.5515224],[-72.1035239,18.5502417],[-72.1028701,18.5503062],[-72.1029015,18.55025],[-72.1028457,18.5501773],[-72.1035081,18.5500252],[-72.103491,18.5497396],[-72.1035181,18.5497361],[-72.1035398,18.5489039],[-72.1034317,18.5487056],[-72.102717,18.5481437],[-72.1025601,18.5481536],[-72.10229,18.5482751],[-72.1022891,18.5482569],[-72.1025201,18.5481396],[-72.1023388,18.5481321],[-72.0999082,18.5480901],[-72.09907,18.5483799],[-72.098878,18.54843]],[[-72.2542503,18.568262],[-72.2560252,18.5717765],[-72.2557886,18.5748049],[-72.2535009,18.5755526],[-72.2522782,18.5755526],[-72.2499906,18.5740945],[-72.2473874,18.5698323],[-72.2460069,18.566729],[-72.2458492,18.5629527],[-72.2479396,18.5625414],[-72.2501483,18.5628031],[-72.2519232,18.5650839],[-72.2542503,18.568262]],[[-72.303145,18.5332749],[-72.3031275,18.5331799],[-72.3048311,18.5311081],[-72.3097397,18.5311081],[-72.3164332,18.5324302],[-72.3234056,18.5366083],[-72.3261388,18.5387765],[-72.3261946,18.5426371],[-72.3170468,18.5540596],[-72.3130864,18.5540596],[-72.2987511,18.5453342],[-72.2988627,18.5407333],[-72.2962969,18.5404689],[-72.2954602,18.5395169],[-72.2961853,18.5338582],[-72.2971893,18.5332235],[-72.3007034,18.5332764],[-72.3022652,18.5342284],[-72.3028486,18.5335189],[-72.303104,18.5333361],[-72.303181,18.5334007],[-72.3035793,18.5335614],[-72.3030793,18.5346463],[-72.303715,18.5339873],[-72.3045286,18.5344052],[-72.3044015,18.5345097],[-72.3062747,18.5352571],[-72.3063107,18.5352741],[-72.3061219,18.5357628],[-72.3061219,18.5358196],[-72.30637,18.5358928],[-72.3062726,18.5354869],[-72.3066688,18.5350891],[-72.3061963,18.5349706],[-72.3058869,18.5349385],[-72.3055373,18.5346833],[-72.3054864,18.534613],[-72.3055585,18.5345065],[-72.3046749,18.5342293],[-72.3047617,18.5338817],[-72.3043252,18.5337511],[-72.3042595,18.5336346],[-72.303145,18.5332749]],[[-72.2981405,18.477502],[-72.2935652,18.4948587],[-72.2922242,18.4964297],[-72.2931708,18.4972526],[-72.2892266,18.5057058],[-72.2878067,18.5080996],[-72.2850458,18.5119893],[-72.2840203,18.5113161],[-72.2808649,18.515879],[-72.2773151,18.5175994],[-72.2723454,18.5175246],[-72.2662714,18.5144578],[-72.2665869,18.5066783],[-72.2692643,18.5046154],[-72.2661965,18.5029756],[-72.2688181,18.4965222],[-72.2691528,18.4959403],[-72.2702684,18.4961519],[-72.2702684,18.4955964],[-72.2690691,18.49557],[-72.2692922,18.4937714],[-72.2736988,18.4859951],[-72.2746749,18.4850429],[-72.2751769,18.483403],[-72.2765435,18.4813398],[-72.2773523,18.4814985],[-72.2783006,18.4809694],[-72.2778544,18.4807049],[-72.2771013,18.480123],[-72.2789978,18.4775836],[-72.279723,18.4772927],[-72.2806433,18.4776365],[-72.2813685,18.4771604],[-72.2808386,18.4769752],[-72.2812848,18.4758378],[-72.2823167,18.4751765],[-72.2851615,18.4750971],[-72.2849941,18.4763668],[-72.2854404,18.4769752],[-72.286277,18.4756262],[-72.2869325,18.4754675],[-72.2865978,18.4751897],[-72.2865978,18.4750046],[-72.2909765,18.4747268],[-72.2946579,18.4749384],[-72.2973911,18.476843],[-72.2981405,18.477502]],[[-72.3466657,18.5222375],[-72.346833,18.5244325],[-72.3475303,18.5277645],[-72.3455501,18.5291131],[-72.3403069,18.5292189],[-72.3383267,18.5280289],[-72.3369043,18.530118],[-72.3338086,18.5296684],[-72.3289279,18.5270769],[-72.328649,18.5253316],[-72.3292068,18.5232689],[-72.330406,18.5220524],[-72.3321631,18.5221847],[-72.3322467,18.5191963],[-72.3369183,18.5183633],[-72.3382012,18.5184691],[-72.3381454,18.5181782],[-72.3411993,18.5177947],[-72.3454943,18.5171997],[-72.3492595,18.517279],[-72.3504308,18.5188922],[-72.3503472,18.5206112],[-72.3496778,18.5220392],[-72.3466657,18.5222375]],[[-72.3303078,18.5486462],[-72.3429687,18.5508149],[-72.3433236,18.5530585],[-72.3413121,18.5614341],[-72.3390639,18.5613593],[-72.3384723,18.5638271],[-72.3375257,18.5654348],[-72.3348436,18.5650609],[-72.3311755,18.5638271],[-72.3312149,18.5616211],[-72.3232082,18.5606863],[-72.3212361,18.559602],[-72.3208023,18.5587046],[-72.3208811,18.557882],[-72.3259493,18.5580274],[-72.3266186,18.5581993],[-72.3259214,18.5577498],[-72.3250986,18.5573797],[-72.3233767,18.552263],[-72.3245994,18.5478507],[-72.3288986,18.5483742],[-72.329979,18.5489548],[-72.3303078,18.5486462]],[[-72.3231383,18.5269828],[-72.3223434,18.528067],[-72.3209629,18.5279745],[-72.3207816,18.5271282],[-72.3208513,18.5253697],[-72.3214649,18.5249598],[-72.3225666,18.5248937],[-72.3228454,18.52533],[-72.3232359,18.5264804],[-72.3231383,18.5269828]],[[-72.2160832,18.6457752],[-72.2159649,18.6553795],[-72.2030279,18.6558279],[-72.1947057,18.6553421],[-72.1922208,18.6545573],[-72.1920631,18.6521283],[-72.193483,18.6477559],[-72.201253,18.6385249],[-72.2069327,18.6388239],[-72.2120996,18.6424117],[-72.2118068,18.6430591],[-72.2121693,18.6426892],[-72.2127968,18.6427552],[-72.2134662,18.6431252],[-72.2135638,18.6437462],[-72.2154176,18.6443947],[-72.2158909,18.6450301],[-72.2160832,18.6457752]],[[-72.2867654,18.6482017],[-72.2900977,18.6527446],[-72.28981,18.6536532],[-72.2900738,18.6542664],[-72.290721,18.6537667],[-72.2910327,18.6544709],[-72.2912485,18.654221],[-72.29168,18.6558905],[-72.2912245,18.656606],[-72.2922673,18.65597],[-72.2926869,18.6567536],[-72.2930705,18.6567309],[-72.2941253,18.6581846],[-72.2960192,18.6608421],[-72.2959713,18.6619096],[-72.2932862,18.664567],[-72.2906731,18.6659979],[-72.2895943,18.6661342],[-72.2895943,18.6665657],[-72.2877004,18.6664749],[-72.2875805,18.6676559],[-72.2831214,18.6697227],[-72.2796453,18.6696546],[-72.2784311,18.6690787],[-72.2783972,18.6687736],[-72.277736,18.6691671],[-72.2774394,18.669143],[-72.2770071,18.6683159],[-72.2765575,18.6681125],[-72.2765385,18.6680583],[-72.2752319,18.6685239],[-72.2749292,18.6674649],[-72.2746416,18.6674309],[-72.2734668,18.6682145],[-72.2732271,18.6682712],[-72.2726757,18.6671583],[-72.2719147,18.6674288],[-72.2718808,18.6673405],[-72.2688149,18.6681868],[-72.2688269,18.6671761],[-72.2690786,18.6668241],[-72.2688149,18.66679],[-72.2681077,18.6670739],[-72.2676282,18.6673805],[-72.2675563,18.6666878],[-72.266861,18.666949],[-72.2655904,18.6673578],[-72.2654466,18.6670058],[-72.2647514,18.6674146],[-72.2629893,18.6681868],[-72.2628455,18.6681754],[-72.2626537,18.6676076],[-72.2623001,18.6677098],[-72.2624799,18.6679199],[-72.2624799,18.6682322],[-72.262306,18.6682606],[-72.2620963,18.6679654],[-72.2622761,18.6689193],[-72.2601484,18.6688966],[-72.2542749,18.6687944],[-72.2505388,18.6683476],[-72.2504371,18.669536],[-72.2477926,18.6698893],[-72.2415204,18.669793],[-72.2414187,18.6741933],[-72.2389167,18.6739759],[-72.2387249,18.6734649],[-72.2383653,18.6733059],[-72.2387009,18.6739532],[-72.2375502,18.6738964],[-72.2374183,18.6735103],[-72.237742,18.67334],[-72.2375142,18.6732605],[-72.236843,18.6734876],[-72.2364354,18.6724088],[-72.2355124,18.6726019],[-72.2354045,18.6724202],[-72.2353027,18.6729028],[-72.2345475,18.6726871],[-72.2343077,18.6724599],[-72.2342358,18.6734706],[-72.2334087,18.6734592],[-72.2332889,18.6733003],[-72.2327375,18.6732889],[-72.2327135,18.6735047],[-72.227703,18.6725281],[-72.2265283,18.6716537],[-72.226804,18.6715742],[-72.2274993,18.6715855],[-72.2274873,18.6714493],[-72.2272899,18.6714623],[-72.2272814,18.6712977],[-72.2272094,18.671358],[-72.2261785,18.6713693],[-72.2256032,18.670881],[-72.2255073,18.6694502],[-72.2261066,18.6696886],[-72.2261785,18.6695949],[-72.2259837,18.6695495],[-72.225777,18.6691379],[-72.2253335,18.6694643],[-72.2249739,18.66947],[-72.2245783,18.6678802],[-72.2235525,18.6677046],[-72.2235907,18.6675921],[-72.2224634,18.6676283],[-72.2223659,18.667022],[-72.2223277,18.6670943],[-72.2219209,18.667026],[-72.2208105,18.6669015],[-72.220809,18.6665325],[-72.2208705,18.6663593],[-72.2206023,18.6668107],[-72.2203895,18.6666361],[-72.2184341,18.6650535],[-72.21829,18.6640979],[-72.2183493,18.6608376],[-72.2187223,18.6606541],[-72.2186894,18.660603],[-72.2187253,18.6604525],[-72.2189771,18.6603247],[-72.2187823,18.6601998],[-72.2186984,18.6602367],[-72.2185815,18.6600352],[-72.2186085,18.6600039],[-72.2187823,18.6601345],[-72.218995,18.6600181],[-72.2189111,18.6599131],[-72.2189681,18.6597938],[-72.2183807,18.6595837],[-72.2184728,18.6539662],[-72.2201001,18.6511554],[-72.225796,18.6469472],[-72.2283048,18.6457265],[-72.2379335,18.645855],[-72.237764,18.6446985],[-72.2400355,18.6432529],[-72.2455958,18.6433493],[-72.2482742,18.6450358],[-72.2487488,18.6436705],[-72.2511067,18.6429775],[-72.2512385,18.6433409],[-72.2512625,18.6431592],[-72.2514843,18.6431365],[-72.2513284,18.6429718],[-72.2533602,18.6423471],[-72.253516,18.6426765],[-72.2539535,18.6425402],[-72.2541453,18.642932],[-72.2543851,18.6428696],[-72.2543791,18.6427503],[-72.2564168,18.6423244],[-72.2566925,18.6431365],[-72.2568783,18.6428582],[-72.2568184,18.6425288],[-72.258843,18.6420991],[-72.258885,18.6422467],[-72.2592626,18.6422297],[-72.2596461,18.6424057],[-72.2592206,18.6406907],[-72.2599545,18.6404815],[-72.2601156,18.6406341],[-72.2601156,18.6399393],[-72.2615268,18.6394669],[-72.2626056,18.6391034],[-72.2654465,18.6387286],[-72.2719433,18.6386832],[-72.272201,18.6388649],[-72.2730341,18.6394158],[-72.273166,18.6412558],[-72.2738732,18.6410286],[-72.2742208,18.6416079],[-72.2752187,18.6416987],[-72.2754524,18.6415738],[-72.2755513,18.6416874],[-72.2755394,18.6417527],[-72.2764713,18.6418634],[-72.276753,18.6418975],[-72.2762953,18.6426002],[-72.2774226,18.6429978],[-72.277982,18.6427247],[-72.2785796,18.6431303],[-72.2785669,18.6432307],[-72.2789017,18.6433471],[-72.279851,18.6439655],[-72.2858703,18.6469651],[-72.2867654,18.6482017]],[[-72.5557247,18.5305893],[-72.5555866,18.5367036],[-72.554995,18.537975],[-72.5488026,18.537919],[-72.5486646,18.5372832],[-72.548842,18.5306267],[-72.5493745,18.5301031],[-72.555133,18.5301218],[-72.5557247,18.5305893]],[[-72.6235278,18.5079877],[-72.6234441,18.5095217],[-72.6226074,18.5104341],[-72.6204878,18.511849],[-72.6183403,18.5107514],[-72.6162207,18.5083183],[-72.6162625,18.506467],[-72.618661,18.5044438],[-72.6204041,18.5044967],[-72.6228305,18.506996],[-72.6235278,18.5079877]]]},{"name":"imagico.de OSM images for mapping: Alaska Range","type":"tms","description":"LC80700162014211LGN00, 2014-07-31 channels 234 (true color), Recent summer image of the Alaska Range for mapping natural features","template":"http://imagico.de/map/osmim_tiles.php?layer=LC80700162014211LGN00&z={zoom}&x={x}&y={-y}","scaleExtent":[0,12],"polygon":[[[-152.708729431479,62.3036424122946],[-152.708729431479,63.5464553885127],[-148.994366411548,63.5464553885127],[-148.994366411548,62.3036424122946],[-152.708729431479,62.3036424122946]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC80700162014211LGN00"},{"name":"imagico.de OSM images for mapping: Bakun Reservoir","type":"tms","description":"LC81190582014075LGN00/LC81180582015183LGN00, 2014-03-16, channels 234 (true color), Missing in older pre-2011 images","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81190582014075LGN00&z={zoom}&x={x}&y={-y}","scaleExtent":[0,13],"polygon":[[[113.53447549873,2.02707458823865],[113.53447549873,3.07076712442006],[114.765167437974,3.07076712442006],[114.765167437974,2.02707458823865],[113.53447549873,2.02707458823865]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC81190582014075LGN00"},{"name":"imagico.de OSM images for mapping: Batam","type":"tms","description":"LC81250592016107LGN00, LC81250602015184LGN00, LC81240602014174LGN00, 2014-2016, channels 234 (true color), Missing Islands in OSM","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81250592016107LGN00&z={zoom}&x={x}&y={-y}","scaleExtent":[0,13],"polygon":[[[104.001374040597,0],[104.001374040597,1.45116299803241],[104.910109782012,1.45116299803241],[104.910109782012,0],[104.001374040597,0]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC81250592016107LGN00"},{"name":"imagico.de OSM images for mapping: Bouvet Island","type":"tms","description":"LC81800982013291LGN00, 2013-10-18, channels 234 (true color), For more accurate coastline and glacier mapping","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81800982013291LGN00&z={zoom}&x={x}&y={-y}","scaleExtent":[0,13],"polygon":[[[3.24652940311363,-54.4705168479877],[3.24652940311363,-54.3753916879791],[3.46391271871771,-54.3753916879791],[3.46391271871771,-54.4705168479877],[3.24652940311363,-54.4705168479877]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC81800982013291LGN00","best":true},{"name":"imagico.de OSM images for mapping: Clerke Rocks","type":"tms","description":"LC82050982015344LGN00, 2015-12-10, channels 234 (true color), Missing in other image sources","template":"http://imagico.de/map/osmim_tiles.php?layer=LC82050982015344LGN00&z={zoom}&x={x}&y={-y}","scaleExtent":[0,13],"polygon":[[[-35.1959928318028,-55.2968852515402],[-35.1959928318028,-54.7209735214882],[-34.1252010131324,-54.7209735214882],[-34.1252010131324,-55.2968852515402],[-35.1959928318028,-55.2968852515402]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC82050982015344LGN00"},{"name":"imagico.de OSM images for mapping: Cotonou","type":"tms","description":"S2A_OPER_PRD_MSIL1C_PDMC_20151222T164644_R022_V20151221T103009_20151221T103009, 2015-12-21, channels 234 (true color), Patchy and partly cloudy coverage in usual sources","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R022_N06_20151221T103009&z={zoom}&x={x}&y={-y}","scaleExtent":[0,14],"polygon":[[[1.83974970187678,6.25776229826032],[1.83974970187678,7.1142717924319],[2.5494187763312,7.1142717924319],[2.5494187763312,6.25776229826032],[1.83974970187678,6.25776229826032]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-S2A_R022_N06_20151221T103009"},{"name":"imagico.de OSM images for mapping: Eastern Devon Island coast","type":"tms","description":"LC80360072014245LGN00/LC80380062014243LGN00, 2014-09-02, channel 654 (false color IR), Coastline mostly mapped meanwhile","template":"http://imagico.de/map/osmim_tiles.php?layer=LC80360072014245LGN00&z={zoom}&x={x}&y={-y}","scaleExtent":[0,11],"polygon":[[[-84.3479873388655,74.3894989734754],[-84.3479873388655,75.8903032392084],[-79.1485833901459,75.8903032392084],[-79.1485833901459,74.3894989734754],[-84.3479873388655,74.3894989734754]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC80360072014245LGN00"},{"name":"imagico.de OSM images for mapping: Eastern Iceland","type":"tms","description":"LC82160152013239LGN00, 2013-08-27, channels 234 (true color), Missing islets and inaccurate coast","template":"http://imagico.de/map/osmim_tiles.php?layer=LC82160152013239LGN00&z={zoom}&x={x}&y={-y}","scaleExtent":[0,12],"polygon":[[[-15.1680535723581,64.2088554380107],[-15.1680535723581,64.8157280042209],[-13.0435379254154,64.8157280042209],[-13.0435379254154,64.2088554380107],[-15.1680535723581,64.2088554380107]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC82160152013239LGN00"},{"name":"imagico.de OSM images for mapping: El Altar","type":"tms","description":"AST_L1T_00302052007154424_20150518041444_91492, 2012-02-05, channels 12x (true color with estimated blue), 2007 ASTER image offering better glacier coverage than common sources","template":"http://imagico.de/map/osmim_tiles.php?layer=AST_L1T_00302052007154424_20150518041444_91492&z={zoom}&x={x}&y={-y}","scaleExtent":[0,14],"polygon":[[[-78.531997745432,-1.8050814821624],[-78.531997745432,-1.60810556500124],[-78.3355811085593,-1.60810556500124],[-78.3355811085593,-1.8050814821624],[-78.531997745432,-1.8050814821624]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-AST_L1T_00302052007154424_20150518041444_91492"},{"name":"imagico.de OSM images for mapping: Elephant Island/Clarence Island","type":"tms","description":"S2A_OPER_PRD_MSIL1C_PDMC_20160109T225906_R009_V20160109T130043_20160109T130043, 2016-01-09, channels 234 (true color), Fairly clear up-to-date image for updating glacier edges","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R009_S61_20160109&z={zoom}&x={x}&y={-y}","scaleExtent":[0,13],"polygon":[[[-56.1347609072749,-61.634696838288],[-56.1347609072749,-60.8398161307814],[-53.723458105877,-60.8398161307814],[-53.723458105877,-61.634696838288],[-56.1347609072749,-61.634696838288]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-S2A_R009_S61_20160109"},{"name":"imagico.de OSM images for mapping: Fogo, Cape Verde","type":"tms","description":"LC82100502015347LGN00, 2015-12-13, channels 234 (true color), Image from after the 2014/2015 eruption","template":"http://imagico.de/map/osmim_tiles.php?layer=LC82100502015347LGN00&z={zoom}&x={x}&y={-y}","scaleExtent":[0,14],"polygon":[[[-24.7587819559676,14.7481298855965],[-24.7587819559676,15.0924935449651],[-24.2670621357462,15.0924935449651],[-24.2670621357462,14.7481298855965],[-24.7587819559676,14.7481298855965]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC82100502015347LGN00"},{"name":"imagico.de OSM images for mapping: Greenland mosaic","type":"tms","description":"mostly Landsat 8 2013-2015 channels 234 (true color), Landsat mosaic of Greenland","template":"http://imagico.de/map/osmim_tiles.php?layer=greenland&z={zoom}&x={x}&y={-y}","scaleExtent":[0,12],"polygon":[[[-43.335169388775576,59.78884556778711],[-43.5940638938192,59.723921705576714],[-43.840898275878764,59.67490148496335],[-44.23515133460447,59.653417915878954],[-44.657213255061194,59.680989005977885],[-45.81015180316172,59.81951972989828],[-46.81057076187592,59.98139710469466],[-47.20837894817284,60.150960472742064],[-47.22064190066637,60.33805731472787],[-47.255916208498,60.42332684576548],[-47.34990349056956,60.446387835215525],[-47.51603887007207,60.45119769375011],[-47.65139646003081,60.48896403744677],[-47.79170835578903,60.52050863908786],[-49.10695022655055,60.73414367492607],[-49.52399924941209,60.97440124547532],[-50.493558334841985,61.089523147855694],[-51.1011476720755,61.3931538528416],[-51.226493283028084,61.8368218735183],[-51.66491000695862,62.06066494936552],[-51.98744899262875,62.355028063412306],[-52.04791761614332,62.676138274608135],[-52.68385390751712,62.89777335327022],[-53.00141158114564,63.22960936121321],[-52.98804591383922,63.665519960839994],[-53.37455124039754,63.88257990608798],[-53.462018437442744,64.21700667649995],[-53.625006563694996,64.39608940752123],[-53.62418230433685,64.87666336480167],[-53.92737410039694,65.14174166474336],[-54.58568916434171,65.51879633173807],[-55.020580045260964,66.04786962007503],[-54.974959716968506,66.43747058777413],[-55.04621700056885,66.81068389526814],[-55.18883177742317,67.07445292724583],[-55.295917291513724,67.2980754937805],[-55.49386806070968,67.62765205772878],[-55.58982586875712,67.74762927352513],[-55.800191618857184,68.05623485476666],[-56.166042896634444,68.44155152338232],[-56.086954623441976,68.68479069915158],[-55.692397350070934,69.09499941753234],[-55.78268862269791,69.35591450732602],[-55.97508469715559,69.51460160299163],[-56.22131441053026,69.61961934478276],[-56.28674985487528,69.75311038137812],[-56.27734150260429,69.86115681621736],[-56.47867255356253,69.98628865160101],[-56.729667549723445,70.20797294037203],[-56.780049018329095,70.4030123058809],[-56.66995480486827,70.53429026926025],[-56.76965573535976,70.59936425752305],[-56.750047814068225,70.67605894741244],[-56.630475021762926,70.75228057874938],[-56.63957096755714,70.79345598378389],[-56.95453022049966,70.92185386457368],[-57.682941688207656,71.10356260725686],[-57.9990573064922,71.18275256548473],[-58.06673093129251,71.31878823942327],[-57.73776694812512,71.73468567987527],[-57.688607830732714,71.96425305773354],[-57.29627634430133,72.25939767922573],[-57.027097307050845,72.49722993388094],[-57.22262816078322,72.61296218481311],[-57.61910829550675,72.72652221937263],[-58.05813139640902,73.01331566875426],[-58.76645057271363,73.2808359719379],[-59.14761885260487,73.53482225342569],[-59.03651118375505,73.80651043385626],[-58.8823279108656,74.19210040380365],[-59.24788269229215,74.4273495816669],[-59.99510425025614,74.65678100854564],[-60.806460490534164,74.7868931828055],[-61.54936387752781,74.99717139513008],[-62.44046860998914,75.00073689358435],[-62.985115364477565,75.11722591645595],[-63.51928606785155,75.31691397958907],[-63.64288486720879,75.52488932122031],[-64.1242392273263,75.5921799154749],[-64.58761243996756,75.53593567213079],[-65.31057987327657,75.42103306523184],[-65.99461388511591,75.4041967649632],[-66.28964875049822,75.41792163747078],[-68.76453492310549,75.13410011250316],[-71.04622564987365,74.79937286637706],[-73.5067977908339,75.97399646374085],[-74.5601685819203,76.43273848659732],[-74.5601685819203,82.6959322619224],[-12.86174239943403,82.6959322619224],[-11.878165975221727,82.54102593940235],[-10.7797834094343,82.51187042401891],[-10.7797834094343,78.34458993192563],[-10.838211677734567,78.32665786610472],[-12.549216515959552,77.9578508228317],[-12.803493182847879,77.85845362808246],[-12.916087338718654,77.65848905807152],[-13.070950321133406,77.52877948776312],[-13.47955419255021,77.40221679143431],[-14.13060832134256,77.30552053875587],[-14.69541342101231,77.14674387861214],[-14.882617750618206,76.84736003108713],[-14.323648701941867,76.53205658256601],[-12.810144796765599,76.24823964501138],[-12.151831546734856,75.86267532270129],[-12.987745033472448,75.38717284756257],[-14.066766809859267,74.8451997920592],[-15.423357647282502,74.4551642069618],[-17.28174157007599,74.24584688808936],[-19.113380020736102,73.72978765991853],[-20.062373344103577,73.11108267968514],[-20.162312506727517,72.6186060300425],[-19.85354831628143,72.0718529721276],[-19.943252248300748,71.55019790921727],[-20.918542646451737,70.67423312425346],[-21.379621573201593,70.27938590726379],[-21.725469254364587,70.05299977015657],[-21.93869730345768,69.92215619574657],[-22.463306498894173,69.6235894257334],[-23.059252433112615,69.5491649852365],[-23.860796144964162,69.34443527043162],[-24.74741743781591,68.93340370554307],[-25.481987646795183,68.76711754662492],[-25.815395630476477,68.51279831615729],[-26.344103298317982,68.32443780018751],[-27.449680541202035,68.19315579455328],[-28.42826258633533,67.66140945836786],[-29.237141834543507,67.60310787132272],[-30.062476147434136,67.41414423917192],[-31.96817868027385,66.21262359095492],[-33.33718066100074,65.93894291103432],[-33.86781919039464,65.7415652217968],[-34.94415141573626,65.29121928843726],[-36.438872573697054,65.22802281646563],[-36.716767002697864,65.14683055370199],[-36.97927615837815,64.90967633661491],[-37.473922616631825,64.38546237809376],[-38.95785728548117,62.7419538908273],[-39.61555442323402,61.96904156671025],[-40.549088272349444,60.92614046823071],[-41.17137829347243,60.43812852329213],[-42.07544989793619,60.311876129737485],[-42.734129957211564,60.001556976048406],[-43.335169388775576,59.78884556778711]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-greenland"},{"name":"imagico.de OSM images for mapping: Heard Island coast","type":"tms","description":"S2A_OPER_PRD_MSIL1C_PDMC_20160412T212111_R047_V20160411T044330_20160411T044330, 2016-04-12, channels 234 (true color), Recent image of Heard island with interior mostly cloud covered but mostly well visible coast","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R047_S54_20160411T044330&z={zoom}&x={x}&y={-y}","scaleExtent":[0,13],"polygon":[[[73.0689652102818,-53.2705500548086],[73.0689652102818,-52.8754896362687],[74.0885530577575,-52.8754896362687],[74.0885530577575,-53.2705500548086],[73.0689652102818,-53.2705500548086]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-S2A_R047_S54_20160411T044330"},{"name":"imagico.de OSM images for mapping: Isla Londonderry","type":"tms","description":"LC82280982013259LGN00, 2013-09-16, channel 654 (false color IR), A lot of very coarse coastlines could be improved here, much snow cover though so no use for glacier mapping","template":"http://imagico.de/map/osmim_tiles.php?layer=LC82280982013259LGN00&z={zoom}&x={x}&y={-y}","scaleExtent":[0,12],"polygon":[[[-72.2652065929688,-55.5594608405404],[-72.2652065929688,-54.178890106312],[-69.4910293325508,-54.178890106312],[-69.4910293325508,-55.5594608405404],[-72.2652065929688,-55.5594608405404]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC82280982013259LGN00"},{"name":"imagico.de OSM images for mapping: Leskov Island ASTER","type":"tms","description":"AST_L1T_00311162013112731_20150618142416_109190, 2013-11-16, channels 12x (true color with estimated blue), Missing in other image sources","template":"http://imagico.de/map/osmim_tiles.php?layer=AST_L1T_00311162013112731_20150618142416_109190&z={zoom}&x={x}&y={-y}","scaleExtent":[0,13],"polygon":[[[-28.2107470814065,-56.721108415345],[-28.2107470814065,-56.6249750430891],[-27.9696123096903,-56.6249750430891],[-27.9696123096903,-56.721108415345],[-28.2107470814065,-56.721108415345]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-AST_L1T_00311162013112731_20150618142416_109190"},{"name":"imagico.de OSM images for mapping: Leskov Island Landsat","type":"tms","description":"LC81991002015286LGN00, 2015-10-13, channels 234 (true color), Missing in other image sources","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81991002015286LGN00&z={zoom}&x={x}&y={-y}","scaleExtent":[0,13],"polygon":[[[-28.2277611728877,-56.7347696464053],[-28.2277611728877,-56.6007525373185],[-27.9690463710613,-56.6007525373185],[-27.9690463710613,-56.7347696464053],[-28.2277611728877,-56.7347696464053]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC81991002015286LGN00"},{"name":"imagico.de OSM images for mapping: May 2013 off-nadir Landsat","type":"tms","description":"LC80372442013137LGN01-LC80530012013137LGN01, 2013-05-17, channels 234 (true color), Only available image north of the regular Landsat limit, mostly with seasonal snow cover so difficult to interpret","template":"http://imagico.de/map/osmim_tiles.php?layer=ls_polar&z={zoom}&x={x}&y={-y}","scaleExtent":[0,10],"polygon":[[[-89.8315284119521,81.3934028410464],[-89.8315284119521,83.7045077508689],[-17.9663056823904,83.7045077508689],[-17.9663056823904,81.3934028410464],[-89.8315284119521,81.3934028410464]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-ls_polar"},{"name":"imagico.de OSM images for mapping: New Ireland","type":"tms","description":"LC80940622015159LGN00, 2015-06-08, channels 234 (true color), Many missing islands in OSM (mostly mapped meanwhile)","template":"http://imagico.de/map/osmim_tiles.php?layer=LC80940622015159LGN00&z={zoom}&x={x}&y={-y}","scaleExtent":[0,14],"polygon":[[[150.388533766196,-2.80056783608088],[150.388533766196,-2.38339617820643],[150.833478309574,-2.38339617820643],[150.833478309574,-2.80056783608088],[150.388533766196,-2.80056783608088]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC80940622015159LGN00"},{"name":"imagico.de OSM images for mapping: Northern Ellesmere Island","type":"tms","description":"ASTER L1T, 2012-07-09/2012-07-15, channels 12x (true color with estimated blue), Assembled from July 2012 ASTER imagery","template":"http://imagico.de/map/osmim_tiles.php?layer=nellesmere_ast&z={zoom}&x={x}&y={-y}","scaleExtent":[0,10],"polygon":[[[-83.0313625595429,82.4597689567848],[-83.0313625595429,83.0958397705009],[-65.6583851391606,83.0958397705009],[-65.6583851391606,82.4597689567848],[-83.0313625595429,82.4597689567848]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-nellesmere_ast"},{"name":"imagico.de OSM images for mapping: Northern German west coast tidalflats","type":"tms","description":"LC81960222015233LGN00, 2015-08-21 channels 134 (true color), Up-to-date low tide imagery of the coast for updating mapping of tidalflats and shoals","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81960222015233LGN00vis&z={zoom}&x={x}&y={-y}","scaleExtent":[0,12],"polygon":[[[7.63567991501593,53.2802190281286],[7.63567991501593,55.502457780526],[9.20773166222509,55.502457780526],[9.20773166222509,53.2802190281286],[7.63567991501593,53.2802190281286]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC81960222015233LGN00vis"},{"name":"imagico.de OSM images for mapping: Northern German west coast tidalflats (infrared)","type":"tms","description":"LC81960222015233LGN00, 2015-08-21 channel 654 (false color IR), Up-to-date low tide imagery of the coast for updating mapping of tidalflats and shoals","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81960222015233LGN00ir&z={zoom}&x={x}&y={-y}","scaleExtent":[0,12],"polygon":[[[7.63567991501593,53.2802190281286],[7.63567991501593,55.502457780526],[9.20773166222509,55.502457780526],[9.20773166222509,53.2802190281286],[7.63567991501593,53.2802190281286]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC81960222015233LGN00ir"},{"name":"imagico.de OSM images for mapping: Northern Greenland ASTER","type":"tms","description":"ASTER L1T, 2005-06-21 to 2012-08-13, channels 12x (true color with estimated blue), Assembled from mostly 2012 ASTER imagery, some 2005 images mainly in the northeast","template":"http://imagico.de/map/osmim_tiles.php?layer=ngreenland_ast&z={zoom}&x={x}&y={-y}","scaleExtent":[0,10],"polygon":[[[-52.49221819431,82.4897991404581],[-52.49221819431,83.7321400994933],[-21.1842327268577,83.7321400994933],[-21.1842327268577,82.4897991404581],[-52.49221819431,82.4897991404581]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-ngreenland_ast"},{"name":"imagico.de OSM images for mapping: Northwest Heard Island","type":"tms","description":"EO1A1350972013086110KF, 2013-03-13, channels 973 (false color IR), Glaciers of Northwest Heard Island (mapped meanwhile)","template":"http://imagico.de/map/osmim_tiles.php?layer=EO1A1350972013086110KF&z={zoom}&x={x}&y={-y}","scaleExtent":[0,13],"polygon":[[[73.2279041335011,-53.2033655831056],[73.2279041335011,-52.9494391381048],[73.7898811920934,-52.9494391381048],[73.7898811920934,-53.2033655831056],[73.2279041335011,-53.2033655831056]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-EO1A1350972013086110KF"},{"name":"imagico.de OSM images for mapping: Panama Canal","type":"tms","description":"S2A_OPER_PRD_MSIL1C_PDMC_20160607T121312_R111_V20160604T154554_20160604T154554, 2016-06-07, channels 234 (true color), Images of the new locks (but partly cloudy)","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R111_N09_20160604T154554&z={zoom}&x={x}&y={-y}","scaleExtent":[0,14],"polygon":[[[-80.0165356176622,8.84894832639322],[-80.0165356176622,9.41480707574399],[-79.4685632943493,9.41480707574399],[-79.4685632943493,8.84894832639322],[-80.0165356176622,8.84894832639322]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-S2A_R111_N09_20160604T154554"},{"name":"imagico.de OSM images for mapping: Pensacola Mountains","type":"tms","description":"LC81511242016033LGN00/LC81511232016033LGN00, 2016-02-02, channels 234 (true color), Outside regular Landsat coverage and therefore not in LIMA and Bing/Mapbox","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81511242016033LGN00&z={zoom}&x={x}&y={-y}","scaleExtent":[0,10],"polygon":[[[-60.6153778814062,-84.1252820431153],[-60.6153778814062,-82.299687854391],[-44.5135525206644,-82.299687854391],[-44.5135525206644,-84.1252820431153],[-60.6153778814062,-84.1252820431153]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC81511242016033LGN00"},{"name":"imagico.de OSM images for mapping: Prokletije Mountains","type":"tms","description":"S2A_OPER_PRD_MSIL1C_PDMC_20160316T034950_R136_V20150831T093006_20150831T093006, 2015-08-31, channels 234 (true color), Late summer imagery where usual sources are severely limited by clouds and snow","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R136_N41_20150831T093006&z={zoom}&x={x}&y={-y}","scaleExtent":[0,14],"polygon":[[[19.0842590534772,42.1531616550022],[19.0842590534772,43.0960297809089],[20.6378953373619,43.0960297809089],[20.6378953373619,42.1531616550022],[19.0842590534772,42.1531616550022]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-S2A_R136_N41_20150831T093006"},{"name":"imagico.de OSM images for mapping: Qasigiannguit","type":"tms","description":"DMS_1142622_03746_20110415_17533956, 2011-04-15, true color, Icebridge DMS image of the settlement - alignment might be poor","template":"http://imagico.de/map/osmim_tiles.php?layer=DMS_1142622_03746_20110415_17533956&z={zoom}&x={x}&y={-y}","scaleExtent":[0,15],"polygon":[[[-51.2433353705628,68.7997259148871],[-51.2433353705628,68.8530261295114],[-51.140370472697,68.8530261295114],[-51.140370472697,68.7997259148871],[-51.2433353705628,68.7997259148871]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-DMS_1142622_03746_20110415_17533956"},{"name":"imagico.de OSM images for mapping: Rann of Kutch","type":"tms","description":"various Landsat early 2015, channel 654 (false color IR), Land/water distinction difficult to properly map based on Bing/Mapbox images","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81510432015030LGN00&z={zoom}&x={x}&y={-y}","scaleExtent":[0,12],"polygon":[[[67.8623118572194,22.3626187997331],[67.8623118572194,24.8869308169273],[71.4900144016907,24.8869308169273],[71.4900144016907,22.3626187997331],[67.8623118572194,22.3626187997331]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC81510432015030LGN00"},{"name":"imagico.de OSM images for mapping: Rila and Pirin Mountains","type":"tms","description":"S2A_OPER_PRD_MSIL1C_PDMC_20160412T121341_R093_V20150828T092005_20150828T092005, 2015-08-28, channels 234 (true color), Late summer imagery where usual sources are severely limited by clouds and snow","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R093_N41_20150828T092005&z={zoom}&x={x}&y={-y}","scaleExtent":[0,14],"polygon":[[[22.9923796970391,41.5848941590232],[22.9923796970391,42.2998374736026],[23.9940012388324,42.2998374736026],[23.9940012388324,41.5848941590232],[22.9923796970391,41.5848941590232]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-S2A_R093_N41_20150828T092005"},{"name":"imagico.de OSM images for mapping: Rwenzori Mountains","type":"tms","description":"LC81730602015040LGN00, 2015-02-09, channel 654 (false color IR), Recent image of most of the remaining Rwenzori Mountains glaciers","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81730602015040LGN00&z={zoom}&x={x}&y={-y}","scaleExtent":[0,13],"polygon":[[[29.7662967768464,0.20687257729646],[29.7662967768464,0.509176367154027],[30.0346684679771,0.509176367154027],[30.0346684679771,0.20687257729646],[29.7662967768464,0.20687257729646]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC81730602015040LGN00"},{"name":"imagico.de OSM images for mapping: Scott Island","type":"tms","description":"LC80611072014036LGN00, 2014-02-05, channels 234 (true color), Missing in other image sources","template":"http://imagico.de/map/osmim_tiles.php?layer=LC80611072014036LGN00&z={zoom}&x={x}&y={-y}","scaleExtent":[0,13],"polygon":[[[-180,-67.4263452022474],[-180,-67.3252448474477],[-179.824753575046,-67.3252448474477],[-179.824753575046,-67.4263452022474],[-180,-67.4263452022474]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC80611072014036LGN00"},{"name":"imagico.de OSM images for mapping: Shag Rocks","type":"tms","description":"LC82100972015347LGN00, 2015-12-13, channels 234 (true color), Missing in other image sources","template":"http://imagico.de/map/osmim_tiles.php?layer=LC82100972015347LGN00&z={zoom}&x={x}&y={-y}","scaleExtent":[0,13],"polygon":[[[-42.1462581850356,-53.7205050698923],[-42.1462581850356,-53.4458622334244],[-41.6557780399063,-53.4458622334244],[-41.6557780399063,-53.7205050698923],[-42.1462581850356,-53.7205050698923]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC82100972015347LGN00"},{"name":"imagico.de OSM images for mapping: Southeastern Sulawesi","type":"tms","description":"LC81130622013270LGN00, 2013-09-27, channels 234 (true color), Missing islands and coarse coastline due to cloud cover in Bing, lakes could also use additional detail","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81130622013270LGN00&z={zoom}&x={x}&y={-y}","scaleExtent":[0,13],"polygon":[[[120.843824420484,-3.59549835456283],[120.843824420484,-2.51468168634705],[122.626180758858,-2.51468168634705],[122.626180758858,-3.59549835456283],[120.843824420484,-3.59549835456283]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC81130622013270LGN00"},{"name":"imagico.de OSM images for mapping: Southern Transantarctic Mountains","type":"tms","description":"LC80281222016035LGN00/LC80281212016035LGN00, 2016-02-04, channels 234 (true color), Outside regular Landsat coverage and therefore not in LIMA and Bing/Mapbox","template":"http://imagico.de/map/osmim_tiles.php?layer=LC80281222016035LGN00&z={zoom}&x={x}&y={-y}","scaleExtent":[0,10],"polygon":[[[154.508575968435,-84.5010049969839],[154.508575968435,-82.5848702651189],[177.005570718893,-82.5848702651189],[177.005570718893,-84.5010049969839],[154.508575968435,-84.5010049969839]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC80281222016035LGN00"},{"name":"imagico.de OSM images for mapping: Thule Air Base","type":"tms","description":"DMS_1142636_16001_20110507_18221638-DMS_1142636_16076_20110507_18224996, 2011-05-07, true color, Icebridge DMS image - alignment might be poor","template":"http://imagico.de/map/osmim_tiles.php?layer=DMS_1142636_160xx_20110507_1822xxxx&z={zoom}&x={x}&y={-y}","scaleExtent":[0,15],"polygon":[[[-68.9397691752981,76.5113260720978],[-68.9397691752981,76.5517569988038],[-68.5074010458985,76.5517569988038],[-68.5074010458985,76.5113260720978],[-68.9397691752981,76.5113260720978]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-DMS_1142636_160xx_20110507_1822xxxx"},{"name":"imagico.de OSM images for mapping: Vanatinai","type":"tms","description":"LC80910682014358LGN00, 2014-12-24, channels 234 (true color), Coarse coastline due to cloud cover in Bing/Mapbox","template":"http://imagico.de/map/osmim_tiles.php?layer=LC80910682014358LGN00&z={zoom}&x={x}&y={-y}","scaleExtent":[0,13],"polygon":[[[153.061381062565,-11.7892410342423],[153.061381062565,-11.0722925205757],[154.411998092239,-11.0722925205757],[154.411998092239,-11.7892410342423],[153.061381062565,-11.7892410342423]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC80910682014358LGN00"},{"name":"imagico.de OSM images for mapping: Volcán Calbuco","type":"tms","description":"LC82330892016031LGN00, 2016-01-31, channels 234 (true color), Image from after the 2015 eruption","template":"http://imagico.de/map/osmim_tiles.php?layer=LC82330892016031LGN00&z={zoom}&x={x}&y={-y}","scaleExtent":[0,13],"polygon":[[[-72.8669610523419,-41.5174389446875],[-72.8669610523419,-41.045274923011],[-71.8751580966041,-41.045274923011],[-71.8751580966041,-41.5174389446875],[-72.8669610523419,-41.5174389446875]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC82330892016031LGN00"},{"name":"imagico.de OSM images for mapping: Western Karakoram","type":"tms","description":"LC81490352013282LGN00, 2013-10-09, channels 234 (true color), Represents approximately minimum snow cover so can be well used for glacier mapping","template":"http://imagico.de/map/osmim_tiles.php?layer=LC81490352013282LGN00&z={zoom}&x={x}&y={-y}","scaleExtent":[0,13],"polygon":[[[73.9309166917002,34.9688073863467],[73.9309166917002,37.0985693236903],[76.5270029470414,37.0985693236903],[76.5270029470414,34.9688073863467],[73.9309166917002,34.9688073863467]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-LC81490352013282LGN00"},{"name":"imagico.de OSM images for mapping: Willkanuta Mountains and Quelccaya Ice Cap","type":"tms","description":"S2A_OPER_PRD_MSIL1C_PDMC_20160511T025410_R039_V20160510T145731_20160510T150701, 2016-05-10, channels 234 (true color), Poor and outdated imagery in other sources","template":"http://imagico.de/map/osmim_tiles.php?layer=S2A_R039_S15_20160510T145731&z={zoom}&x={x}&y={-y}","scaleExtent":[0,14],"polygon":[[[-71.1807064830626,-14.4978825528812],[-71.1807064830626,-13.7102928800508],[-70.5563773605996,-13.7102928800508],[-70.5563773605996,-14.4978825528812],[-71.1807064830626,-14.4978825528812]]],"terms_url":"http://maps.imagico.de/#osmim","terms_text":"imagico.de OSM images for mapping","id":"osmim-imagicode-S2A_R039_S15_20160510T145731"},{"name":"Interspect ortofotó 2014","type":"tms","description":"Four districts of Budapest: III, XIII, XIV, XV","template":"http://geoserver.infobex.hu/Budapest2014/IST/{zoom}/{x}/{y}.jpg","scaleExtent":[10,21],"polygon":[[[19.04642,47.61098],[19.05375,47.60995],[19.06033,47.61037],[19.06022,47.61009],[19.06091,47.61023],[19.0755,47.60835],[19.07796,47.60718],[19.07773,47.60627],[19.07599,47.60433],[19.07337,47.59906],[19.07232,47.59332],[19.0723,47.58865],[19.0693,47.5798],[19.06891,47.57742],[19.06949,47.57211],[19.06623,47.56375],[19.06717,47.56427],[19.0692,47.56456],[19.06992,47.56418],[19.07011,47.56363],[19.07785,47.56148],[19.07986,47.56053],[19.08359,47.55604],[19.08516,47.5548],[19.08601,47.5551],[19.08703,47.55488],[19.0984,47.54666],[19.09974,47.54692],[19.10094,47.54656],[19.1015,47.54593],[19.1015,47.54523],[19.10255,47.54458],[19.10939,47.56255],[19.10917,47.56324],[19.11193,47.57058],[19.11235,47.57087],[19.11271,47.57297],[19.11382,47.57379],[19.1144,47.57504],[19.11779,47.58375],[19.11774,47.5844],[19.11844,47.58512],[19.12,47.58924],[19.12008,47.59563],[19.1206,47.59856],[19.12127,47.59952],[19.12266,47.6004],[19.12436,47.6008],[19.1255,47.60048],[19.12577,47.5997],[19.128,47.59885],[19.13058,47.59898],[19.13768,47.60057],[19.13874,47.60043],[19.14144,47.59639],[19.14122,47.59568],[19.14023,47.59527],[19.15557,47.58499],[19.15413,47.58389],[19.15329,47.58013],[19.15344,47.57918],[19.15499,47.57884],[19.16043,47.57871],[19.16043,47.57583],[19.16213,47.57583],[19.16196,47.57383],[19.17573,47.56442],[19.17511,47.56345],[19.16356,47.55986],[19.16295,47.5594],[19.17589,47.55134],[19.18156,47.54896],[19.18205,47.5483],[19.18165,47.54762],[19.16905,47.53994],[19.15316,47.52885],[19.14747,47.52584],[19.14691,47.52332],[19.14947,47.52059],[19.15581,47.51256],[19.1572,47.51155],[19.15697,47.51051],[19.15885,47.50566],[19.15866,47.50493],[19.15793,47.50438],[19.10292,47.49828],[19.1016,47.49846],[19.10057,47.49914],[19.09185,47.5003],[19.08953,47.50117],[19.07138,47.51722],[19.06794,47.51558],[19.06631,47.51529],[19.06522,47.51545],[19.06347,47.51668],[19.06072,47.51512],[19.05709,47.51044],[19.05567,47.50992],[19.05417,47.50997],[19.04318,47.51383],[19.04093,47.51397],[19.04045,47.51449],[19.03916,47.51909],[19.03898,47.52143],[19.03938,47.52358],[19.04081,47.52649],[19.0408,47.53092],[19.02088,47.53091],[19.02088,47.529],[19.0172,47.52866],[19.01684,47.52876],[19.01453,47.53356],[19.01459,47.5347],[19.01373,47.5348],[19.01167,47.53786],[19.01055,47.53839],[19.0051,47.53978],[19.00501,47.54075],[19.00761,47.54245],[19.00684,47.54297],[19.00684,47.54385],[19.00525,47.54499],[19.0053,47.5455],[19.00462,47.54557],[19.00434,47.54599],[19.00261,47.55075],[18.99714,47.55468],[18.99466,47.55877],[18.99244,47.5605],[18.99173,47.56266],[18.99105,47.56278],[18.986,47.56863],[18.97914,47.57257],[18.97675,47.57301],[18.97622,47.57444],[18.97677,47.57463],[18.97641,47.57596],[18.98247,47.58127],[18.98227,47.58198],[18.98276,47.58283],[18.97695,47.58448],[18.97645,47.58485],[18.97639,47.58555],[18.98285,47.58936],[18.9841,47.58929],[18.99076,47.58612],[18.99375,47.58507],[18.99618,47.58645],[18.99727,47.58664],[19.00068,47.58457],[19.0016,47.58438],[19.00892,47.58637],[19.01088,47.58637],[19.01088,47.5869],[19.01264,47.58738],[19.02151,47.58876],[19.02593,47.58914],[19.03271,47.5883],[19.03199,47.59087],[19.03113,47.59163],[19.03125,47.59276],[19.02883,47.59838],[19.02808,47.59978],[19.0239,47.60425],[19.02393,47.60498],[19.02531,47.60575],[19.03768,47.6104],[19.04642,47.61098]]],"terms_url":"http://interspect.hu/","terms_text":"Interspect Kft.","best":true},{"name":"Ireland Bartholomew Quarter-Inch 1940","type":"tms","template":"http://geo.nls.uk/maps/ireland/bartholomew/{zoom}/{x}/{-y}.png","scaleExtent":[5,13],"polygon":[[[-8.8312773,55.3963337],[-7.3221271,55.398605],[-7.2891331,55.4333162],[-7.2368042,55.4530757],[-7.18881,55.4497995],[-7.1528144,55.3968384],[-6.90561,55.394903],[-6.9047153,55.3842114],[-5.8485282,55.3922956],[-5.8378629,55.248676],[-5.3614762,55.2507024],[-5.3899172,53.8466464],[-5.8734141,53.8487436],[-5.8983,52.8256258],[-6.0191742,52.8256258],[-6.0262844,51.7712367],[-8.1131422,51.7712367],[-8.1273627,51.3268839],[-10.6052842,51.3091083],[-10.6271879,52.0328254],[-10.6469845,52.0322454],[-10.6469845,52.0440365],[-10.6271879,52.0448095],[-10.6290733,52.0745627],[-10.6699234,52.0743695],[-10.6702376,52.0876941],[-10.6312729,52.0898179],[-10.6393128,52.4147202],[-10.3137689,52.4185533],[-10.3166401,53.3341342],[-10.3699669,53.3330727],[-10.385965,54.3534472],[-8.8163777,54.3586265],[-8.8173427,54.6595721],[-8.8413398,54.6616284],[-8.8422286,54.6929749],[-8.8315632,54.7145436],[-8.8151208,54.7145436],[-8.8312773,55.3963337]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps"},{"name":"Ireland British War Office 1:25k GSGS 3906","type":"tms","template":"http://mapwarper.net/layers/tile/101/{zoom}/{x}/{y}.png","scaleExtent":[0,18],"polygon":[[[-10.71,51.32],[-10.71,55.46],[-5.37,55.46],[-5.37,51.32],[-10.71,51.32]]],"terms_url":"http://wiki.openstreetmap.org/wiki/WikiProject_Ireland#Trinity_College_Dublin","terms_text":"Glucksman Map Library, Trinity College Dublin","id":"GSGS3906"},{"name":"Ireland British War Office One-Inch 1941-43 GSGS 4136","type":"tms","template":"http://geo.nls.uk/maps/ireland/gsgs4136/{zoom}/{x}/{-y}.png","scaleExtent":[5,15],"polygon":[[[-10.0847426,51.4147902],[-10.0906535,51.5064103],[-10.4564222,51.5003961],[-10.5005905,52.3043019],[-10.0837522,52.312741],[-10.0840973,52.3404698],[-10.055802,52.3408915],[-10.0768509,52.7628238],[-9.7780248,52.7684611],[-9.7818205,52.8577261],[-9.6337877,52.8596012],[-9.6449626,53.1294502],[-10.0919663,53.1227152],[-10.1051422,53.3912913],[-10.4052593,53.3866349],[-10.4530828,54.193502],[-10.2998523,54.1974988],[-10.3149801,54.4669592],[-8.9276095,54.4853897],[-8.9339534,54.7546562],[-8.7773069,54.755501],[-8.7826749,55.0252208],[-8.9402974,55.0238221],[-8.9451773,55.2934155],[-7.528039,55.2970274],[-7.525599,55.3874955],[-7.0541955,55.3841691],[-7.0556595,55.2939712],[-6.3241545,55.2859128],[-6.3217146,55.3253556],[-6.1035807,55.3223016],[-6.1045566,55.2828557],[-5.7985836,55.2772968],[-5.8117595,55.0087135],[-5.656577,55.0056351],[-5.6721928,54.7355021],[-5.3618278,54.729585],[-5.3964755,54.1917889],[-5.855679,54.2017807],[-5.9220464,52.8524504],[-6.070885,52.8551025],[-6.1030927,52.1373337],[-6.8331336,52.1463183],[-6.8355736,52.0578908],[-7.5641506,52.0617913],[-7.5661026,51.7921593],[-8.147305,51.792763],[-8.146329,51.7033331],[-8.2912636,51.7027283],[-8.2897996,51.5227274],[-9.1174397,51.516958],[-9.1179277,51.4625685],[-9.3692452,51.4616564],[-9.3672933,51.4254613],[-10.0847426,51.4147902]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps","id":"GSGS4136"},{"name":"Ireland EEA CORINE 2006","type":"tms","template":"http://a.tile.openstreetmap.ie/tiles/corine/{zoom}/{x}/{y}.png","scaleExtent":[5,16],"polygon":[[[-5.842956,53.8627976],[-5.8341575,53.7633541],[-5.6267647,53.5383692],[-5.9648778,52.1631197],[-6.0453211,52.0527275],[-6.1823261,51.9699475],[-6.3960035,51.9234618],[-6.5945978,51.883911],[-7.2481994,51.9056295],[-7.341212,51.8148076],[-8.1971787,51.5037019],[-8.3191005,51.4167737],[-9.4478202,51.1991221],[-9.9015706,51.2266802],[-10.472215,51.4050139],[-10.8857437,51.6770619],[-11.035318,52.0620016],[-10.9950963,52.1831616],[-10.8178697,52.3139827],[-9.8839736,52.9032208],[-10.1165049,52.9676141],[-10.5514014,53.3317027],[-10.6896633,53.5854022],[-10.6444139,54.0100436],[-10.5501445,54.257482],[-10.2824192,54.4742405],[-9.8073011,54.5705346],[-9.196435,54.5486695],[-9.2253443,54.7000264],[-8.8985435,55.1363582],[-8.0476045,55.4711977],[-7.4367384,55.6191092],[-7.2205471,55.6205288],[-6.8258723,55.5608644],[-6.0679458,55.3727567],[-5.5639184,55.0759594],[-5.0649187,54.4640142],[-5.2572284,54.1582424],[-5.842956,53.8627976]]],"terms_url":"http://www.eea.europa.eu/data-and-maps/data/clc-2006-vector-data-version-1","terms_text":"EEA Corine 2006"},{"name":"Ireland EEA GMES Urban Atlas","type":"tms","template":"http://a.tile.openstreetmap.ie/tiles/urbanatlas/{zoom}/{x}/{y}.png","scaleExtent":[5,17],"polygon":[[[-9.2759602,52.7993666],[-9.215509,52.8276933],[-9.1086618,52.9128016],[-9.0196831,52.8837107],[-8.8760649,52.8978445],[-8.8001797,52.8833558],[-8.7665597,52.9065354],[-8.5938079,52.9238592],[-8.5241972,52.8869724],[-8.4956786,52.9105906],[-8.3506448,52.9238592],[-8.2718204,52.9492401],[-8.2249679,52.8991338],[-8.1564001,52.9149986],[-8.0881237,52.7630417],[-8.1360092,52.7239783],[-8.1570652,52.6766443],[-8.2059695,52.6185385],[-8.2025734,52.5954396],[-8.2231242,52.5599691],[-8.2236294,52.5095371],[-8.2976651,52.5025088],[-8.3295888,52.4721087],[-8.3589695,52.4986072],[-8.3737385,52.4764529],[-8.432326,52.4342609],[-8.4754569,52.4216289],[-8.5017727,52.3870011],[-8.5476205,52.3681351],[-8.6444103,52.3376422],[-8.6841451,52.3660614],[-8.8154099,52.3721014],[-8.8614233,52.3521652],[-8.9074451,52.3824674],[-8.9388551,52.3789166],[-8.9782502,52.4093811],[-9.0298715,52.4104169],[-9.1059449,52.420981],[-9.1084962,52.4415071],[-9.140702,52.4650891],[-9.1315765,52.5136207],[-9.1739699,52.5620573],[-9.1426235,52.589645],[-9.1542382,52.610216],[-9.1426231,52.6387401],[-9.1776844,52.6447573],[-9.2012184,52.6526248],[-9.2036198,52.6686468],[-9.2238348,52.6706578],[-9.2161072,52.6919412],[-9.1882395,52.7057242],[-9.2750099,52.7350292],[-9.2601152,52.7616711],[-9.2759602,52.7993666]],[[-7.307313219981238,53.81625879275365],[-7.245858447032101,53.78300449111207],[-7.15144468970801,53.81179938127503],[-7.086900011973722,53.784424420834],[-7.0347149533800435,53.77996162275688],[-6.975320116954343,53.788481098127924],[-6.928628222423156,53.81443454540607],[-6.992829577403537,53.86609081229548],[-6.975320116954343,53.87945028968944],[-6.949914233165313,53.87094929783329],[-6.9375546140247035,53.87540241385127],[-6.936867968516893,53.896649390754646],[-6.897042529063821,53.889770599553906],[-6.867516772227924,53.880259817835736],[-6.851037280040446,53.88450958346468],[-6.842454211192801,53.89786317755242],[-6.812928454356904,53.90069520963246],[-6.79850889869286,53.89280549994937],[-6.789925829845217,53.89462633440526],[-6.791985766368652,53.904538374710896],[-6.778939501720231,53.918087767078354],[-6.77001311011868,53.91505470292794],[-6.75868345923979,53.921727153244476],[-6.744263903575747,53.916065748791254],[-6.727441088634364,53.92334455637637],[-6.713021532970319,53.90777445003927],[-6.684182421642232,53.90292024303218],[-6.623757616954815,53.88187882710815],[-6.590455309825955,53.857789593974296],[-6.591141955333765,53.835509894663346],[-6.574319140392382,53.82254170362619],[-6.571572558361136,53.804703885117576],[-6.5533764524041285,53.79983770791046],[-6.541360156017425,53.78300449111207],[-6.511491076427622,53.76900546961285],[-6.472695605236269,53.77326653566421],[-6.443513171154276,53.76393220797015],[-6.44728972144724,53.75114486961979],[-6.4775021237909485,53.728199094666586],[-6.459649340587848,53.71682309412751],[-6.435616747814443,53.72230833571077],[-6.4198239011347775,53.72921465935537],[-6.4009411496699595,53.72169889975152],[-6.375878588634836,53.718042098526006],[-6.359055773693453,53.708695495259434],[-6.340173022228636,53.708085862042424],[-6.329873339611461,53.71296268045594],[-6.325753466564592,53.72210519137233],[-6.2938244504513525,53.72576163932632],[-6.265328661877173,53.7363229253304],[-6.240952746349864,53.734292114843086],[-6.180871264416349,53.632015710147016],[-6.092793818322125,53.588038288422446],[-5.985734079608837,53.49383447350347],[-6.0887447432153685,53.27174268379562],[-6.033272979232964,53.1191110041494],[-5.984663357119282,52.9651254915577],[-6.122679104189409,52.73207538466633],[-6.185163845400262,52.73706461957944],[-6.1899703639549415,52.76075568810044],[-6.319059719423517,52.782357357522855],[-6.393904079774976,52.7790347214105],[-6.465315212587381,52.6946379192593],[-6.534666408876349,52.673409093161446],[-6.612257351259057,52.69255711803012],[-6.6692489284074155,52.74745702505679],[-6.671308864930852,52.76948072949997],[-6.720747341493285,52.7748810695361],[-6.71456753192298,52.80311808637125],[-6.658949245790243,52.84709806982182],[-6.582044948915348,52.81349473557279],[-6.547712673524768,52.83133677935633],[-6.531233181337292,52.87404491274922],[-6.617750515321548,52.87528820923615],[-6.728987087587023,52.90635903963372],[-6.780485500672891,52.859122574848655],[-6.870436062196207,52.85165948109425],[-6.938413967469552,52.86658438536895],[-6.965879787782016,52.89766145203082],[-6.987852444031986,52.969260966642985],[-7.039350857117853,52.9560260536776],[-7.109388698914634,53.007288776633686],[-7.068876613953752,53.058078015357786],[-7.088789333680287,53.11869890949892],[-7.119688381531809,53.15000684568904],[-7.105955471375577,53.16112391039828],[-7.127928127625547,53.17223809655703],[-7.180113186219227,53.182526443342745],[-7.160887112000503,53.19898266621498],[-7.057890285828767,53.19898266621498],[-7.048963894227218,53.217077217179636],[-7.0915359157115345,53.235575105358386],[-7.0434707301647235,53.25735126035676],[-7.05102383075065,53.29717703664696],[-6.996778835633536,53.31112780504489],[-7.044157375672535,53.33368557548294],[-7.105955471375576,53.371801590024276],[-7.22050647653913,53.432465115081854],[-7.149441429887032,53.45731709817442],[-7.099891489102085,53.463915962572514],[-7.0744645458045445,53.48370640260363],[-7.079028356140001,53.504650927752664],[-7.047733656696876,53.515119311359335],[-7.029478415355053,53.54147267392419],[-7.054253385747527,53.56471202500164],[-7.009267255298033,53.58561652973758],[-6.992641946218873,53.602642188744426],[-6.989056095241016,53.62739453790707],[-6.9717788132567895,53.63686620586593],[-6.9633031654909425,53.650973114934644],[-6.9871001765258205,53.66623418009986],[-6.999813648174589,53.67086935885432],[-7.008289295940436,53.65908728051006],[-7.044473792171549,53.65367801032349],[-7.066640870943764,53.63918547390694],[-7.101847407817279,53.65870092708686],[-7.120754622064167,53.672993645380515],[-7.137379931143327,53.66893809633893],[-7.160850955725672,53.683034277255075],[-7.174216400279507,53.686316272406906],[-7.196057492599188,53.69017711570491],[-7.210726882963154,53.69480966037566],[-7.247237365646801,53.71661437518035],[-7.239413690786019,53.73223735177976],[-7.260276823748104,53.74361339729716],[-7.2814659431627184,53.75922634307083],[-7.289615604476034,53.77271433845693],[-7.3238441819919515,53.78465723043301],[-7.337209626545788,53.78658318504567],[-7.351227044004687,53.80141007448381],[-7.307313219981238,53.81625879275365]],[[-5.685433013282673,54.77854496390836],[-5.696867084279401,54.73050346921268],[-5.8223689524230124,54.70033215177621],[-5.878760568989772,54.649492182564074],[-5.743404719024681,54.68128223623249],[-5.581196917402638,54.68781619319656],[-5.571488953592992,54.67074450064368],[-5.582915011231644,54.66440901595977],[-5.58291501123164,54.65085746679818],[-5.6086481910584185,54.63997082553691],[-5.6354970593650116,54.61551371292451],[-5.728732824433139,54.6184944610979],[-5.822612969913913,54.49193018941315],[-5.896754545381575,54.44975600798866],[-5.936834914186871,54.38213187386197],[-6.0187561190025445,54.36974944197913],[-6.059257912638059,54.38280030737259],[-6.101784280694663,54.41510088826871],[-6.1740201072375225,54.43476829635816],[-6.216261364689026,54.42827259213158],[-6.264329002478664,54.487825014814625],[-6.249277519938476,54.49741303545491],[-6.288340515296785,54.53143435197413],[-6.283750270272458,54.54447449434036],[-6.321445027854273,54.58928767713928],[-6.264329002478664,54.604982769755765],[-6.240052417736423,54.59541999854735],[-6.098762694536575,54.631690374598676],[-6.051950538018501,54.61314575326238],[-6.031509408441251,54.620921248201434],[-6.002995140908084,54.65571636730639],[-6.0647754758974335,54.6634355452454],[-6.059920158948984,54.704134188139534],[-6.047781866577864,54.71395188569398],[-6.120611620804591,54.801644524994515],[-6.002141887262449,54.80836072138932],[-5.984662746248036,54.78652900156178],[-5.685433013282673,54.77854496390836]],[[-9.128658300749114,53.24759266864586],[-9.024510568479629,53.26744820137083],[-9.016360907166316,53.26364619217274],[-9.001854510028616,53.26588844362053],[-8.9951717877517,53.259258838409615],[-8.973493688658284,53.262378780650025],[-8.95230456924367,53.271444820907114],[-8.956705386352859,53.281580911863244],[-8.961106203462048,53.28119110665652],[-8.960780217009516,53.28908396911955],[-8.954260487958864,53.28927883616923],[-8.95230456924367,53.30155366854246],[-8.963714095082308,53.303793931840495],[-8.9811543702928,53.294734752711804],[-8.985718180628256,53.30174847871221],[-9.019946758144176,53.30768976199425],[-9.00837423907927,53.31596722087059],[-9.01880580556031,53.31625933715475],[-9.045862681120513,53.31275380979257],[-9.06444390891487,53.32122500810515],[-9.080906224767762,53.307397587062724],[-9.08106921799403,53.303404329274585],[-9.09019683866494,53.30574189135002],[-9.095901601584261,53.298826232852214],[-9.10128037805105,53.3008718259498],[-9.115623781962478,53.28450433758295],[-9.121491538108067,53.2832375443259],[-9.13273807072044,53.28557621023763],[-9.144636576237877,53.27865728614638],[-9.13876882009229,53.26345120822951],[-9.128658300749114,53.24759266864586]],[[-8.595266214281438,51.69264788483154],[-8.55819409885298,51.69306638852667],[-8.566697711835303,51.682644706464686],[-8.579130708100188,51.67349700898941],[-8.544554623426079,51.66520531197343],[-8.494765061495364,51.667778759675976],[-8.30113898732036,51.7235009029955],[-8.268406960495541,51.784858633837544],[-8.154536388302146,51.7814362126791],[-8.115350159004825,51.809093351533164],[-8.068326683848039,51.870050153657075],[-8.10059769621054,51.89964422561186],[-8.08123508879304,51.918414974037226],[-8.09183842142643,51.95337589170907],[-8.124570448251253,51.95479649105758],[-8.132407694110718,51.970988142592034],[-8.099675667285895,51.978371865876596],[-8.144394070131078,52.02151390085561],[-8.159607547387685,52.064330945363764],[-8.140705954432507,52.07254939152303],[-8.165600735397863,52.09294727054506],[-8.18726841512697,52.0835993998731],[-8.2093971093184,52.10512489114057],[-8.207092037006792,52.12494181389489],[-8.227837687811258,52.143052434929714],[-8.222766528725723,52.16454923557058],[-8.30298304516965,52.1829264222872],[-8.427456949996438,52.17783811526099],[-8.46710419375608,52.169921813849676],[-8.509978538751975,52.18405707812542],[-8.530263175094117,52.16511480067495],[-8.574981577939297,52.18066502436804],[-8.587889982884295,52.16963906274442],[-8.642289689438227,52.18829678149147],[-8.719279104645906,52.15804472022032],[-8.698533453841442,52.13541291452849],[-8.740946784375014,52.10823956240069],[-8.77460084012448,52.05951253229793],[-8.803183736788409,52.03768144571248],[-8.86818677597573,52.03286015807593],[-8.870491848287335,52.01839317543363],[-8.844214023935015,51.991148511559096],[-8.79811257770287,51.964455373040394],[-8.782899100446263,51.931777239822054],[-8.835915763613228,51.9292188160068],[-8.838681850387156,51.90277322850554],[-8.802261707863764,51.89367006943167],[-8.792580404155013,51.85695425263326],[-8.765841565340368,51.82476769939557],[-8.758926348405547,51.80054140901511],[-8.79811257770287,51.78628456602828],[-8.832227647914657,51.79626482935233],[-8.836837792537873,51.77687258059678],[-8.885705325543944,51.746055989869106],[-8.859888515653944,51.72435763090916],[-8.807332866949299,51.71093369500414],[-8.678248817499297,51.693505197270746],[-8.60540853245251,51.67835695335278],[-8.595266214281438,51.69264788483154]],[[-7.138279151048154,55.06131559970097],[-7.117994514706011,54.99631329558348],[-7.070049010624583,54.98784996056705],[-7.076503213097081,54.93332450204895],[-7.025791622241725,54.91159959910791],[-7.007351043748867,54.87872502112528],[-7.024869593317081,54.8511320998998],[-6.990754523105296,54.81661438893913],[-7.051608432131725,54.80598761598125],[-7.115228427932084,54.80651902101645],[-7.170550163410654,54.84847793920564],[-7.199133060074584,54.84316909395457],[-7.222183783190655,54.85803210052931],[-7.2111194360949415,54.862808332627324],[-7.212041465019584,54.882438010878076],[-7.279349576518514,54.880846771447125],[-7.273817402970655,54.91530955931841],[-7.3033223285592275,54.915839525718205],[-7.363254208661015,54.90894941815292],[-7.385382902852443,54.91636948513913],[-7.391837105324943,54.93438395336098],[-7.429640291235302,54.95291983389722],[-7.420420001988872,54.99208185118366],[-7.410277683817801,55.03437621938347],[-7.3577220351131585,55.057619110599035],[-7.265519142648871,55.07557028899173],[-7.138279151048154,55.06131559970097]],[[-7.190498776293322,52.26144368927652],[-7.156844720543858,52.28443443581867],[-7.132871968503143,52.27343421670601],[-7.113278853854483,52.26779201951648],[-7.098295883829036,52.27230583471742],[-7.089767116276089,52.25509445009032],[-7.07109603055207,52.259186286149074],[-7.033984366335195,52.257352061495865],[-7.027530163862696,52.250720000975015],[-7.034675888028678,52.247756419376],[-7.031218279561267,52.24013487190721],[-7.034214873566356,52.23222966213934],[-7.050580886978767,52.2296884028405],[-7.062567262999124,52.21980434486687],[-7.076858711331088,52.216132562953725],[-7.084926464421715,52.22065163604718],[-7.084465449959392,52.22785295843095],[-7.101292477834124,52.221498911062525],[-7.105211100763858,52.21726237433474],[-7.111665303236357,52.21796849185403],[-7.107977187537785,52.21104805609072],[-7.117773744862115,52.20928246619701],[-7.129760120882472,52.21690931136535],[-7.14497359813908,52.21782726924826],[-7.150505771686938,52.22375823207553],[-7.158112510315241,52.22262858593765],[-7.158804032008724,52.22700580464912],[-7.158573524777563,52.23180612902503],[-7.167563306792832,52.23985256723076],[-7.16733279956167,52.244580933687786],[-7.172519212262786,52.24676851484933],[-7.177590371348324,52.25114335361416],[-7.190498776293322,52.26144368927652]]],"terms_url":"http://www.eea.europa.eu/data-and-maps/data/urban-atlas","terms_text":"EEA GMES Urban Atlas"},{"name":"Japan GSI ortho Imagery","type":"tms","template":"http://cyberjapandata.gsi.go.jp/xyz/ort/{z}/{x}/{y}.jpg","scaleExtent":[12,19],"polygon":[[[141.85546875,44.64911632343077],[140.2294921875,43.96909818325174],[138.955078125,41.80407814427237],[139.482421875,40.17887331434696],[138.8671875,38.30718056188316],[136.31835937499997,37.19533058280065],[132.1435546875,35.137879119634185],[128.935546875,33.35806161277885],[129.5068359375,32.47269502206151],[129.77050781249997,31.690781806136822],[130.2099609375,30.90222470517144],[131.220703125,30.78903675126116],[131.66015625,32.32427558887655],[132.71484375,32.879587173066305],[133.76953125,33.17434155100208],[136.7578125,33.87041555094183],[139.306640625,35.06597313798418],[140.888671875,35.17380831799959],[141.15234374999997,36.56260003738548],[142.11914062499997,39.9434364619742],[141.767578125,42.68243539838623],[141.85546875,44.64911632343077]]]},{"name":"Kanton Aargau 25cm (AGIS 2011)","type":"tms","template":"http://tiles.poole.ch/AGIS/OF2011/{zoom}/{x}/{y}.png","scaleExtent":[14,19],"polygon":[[[7.7,47.12],[7.7,47.63],[8.5,47.63],[8.5,47.12],[7.7,47.12]]],"terms_text":"AGIS OF2011"},{"name":"Kanton Aargau 25cm (AGIS 2014)","type":"tms","template":"http://mapproxy.osm.ch:8080/tiles/AGIS2014/EPSG900913/{z}/{x}/{y}.png?origin=nw","scaleExtent":[8,19],"polygon":[[[8.222923278808594,47.604774168947614],[8.244209289550781,47.613569753973955],[8.294334411621094,47.60986653003798],[8.300857543945312,47.58625231278527],[8.329353332519531,47.569808674020344],[8.382568359375,47.56702895728551],[8.398017883300781,47.57490443821351],[8.424797058105469,47.56795554592218],[8.415184020996094,47.54663986006874],[8.389778137207031,47.5262428287156],[8.372268676757812,47.51233121261258],[8.358535766601562,47.503286684046664],[8.36402893066406,47.48078455918],[8.371238708496094,47.481016589036074],[8.373985290527344,47.47011007802331],[8.368148803710938,47.46825342516445],[8.387031555175781,47.44852243794931],[8.380851745605469,47.447593738482304],[8.384284973144531,47.4355191531953],[8.376388549804688,47.431803338643334],[8.377761840820312,47.42808726171425],[8.389434814453125,47.42739046807988],[8.391494750976562,47.41902822496511],[8.380165100097656,47.40462347023052],[8.364715576171875,47.4016026187529],[8.367118835449219,47.39881398671558],[8.380851745605469,47.39788440990287],[8.39424133300781,47.39439835079049],[8.399734497070312,47.372314620566925],[8.40728759765625,47.37068703239024],[8.404197692871094,47.34417352612498],[8.416213989257812,47.33416935720614],[8.414497375488281,47.32602502961836],[8.452606201171875,47.33254059215931],[8.444023132324219,47.31927592106609],[8.427543640136719,47.29925625338924],[8.390121459960938,47.28854494625744],[8.41175079345703,47.247076403108416],[8.393898010253906,47.227728840642065],[8.404884338378906,47.194845099780174],[8.401451110839844,47.17757880776958],[8.409690856933594,47.17314466448546],[8.412437438964844,47.13976002139446],[8.379478454589844,47.13929295458033],[8.361968994140625,47.14559801038333],[8.342742919921875,47.177112073280966],[8.3056640625,47.24987305653909],[8.295021057128906,47.26268916206698],[8.300514221191406,47.26991141830738],[8.278884887695312,47.28225686421767],[8.259315490722656,47.285983225286174],[8.243522644042969,47.280859411143915],[8.240432739257812,47.27130916053537],[8.228759765625,47.27270686584952],[8.219146728515625,47.25336866567523],[8.204727172851562,47.245444953748034],[8.203353881835938,47.22679624955806],[8.180007934570312,47.22143353240336],[8.171768188476562,47.2279619858493],[8.155975341796875,47.23961793870555],[8.175888061523436,47.24218190428504],[8.17657470703125,47.25406775981567],[8.136062622070312,47.24730946320093],[8.12164306640625,47.24218190428504],[8.10791015625,47.2447457457832],[8.097267150878906,47.259427174956194],[8.077354431152344,47.2603591917818],[8.059844970703125,47.25569894358661],[8.062591552734375,47.24614415248379],[8.016586303710938,47.242881146090085],[8.015899658203125,47.258961160390896],[7.997016906738281,47.2796948387185],[7.951698303222655,47.274337475394645],[7.960968017578125,47.25430078914495],[7.933845520019531,47.237053849043896],[7.911529541015624,47.24381345414034],[7.859344482421875,47.23425651880584],[7.83977508544922,47.23425651880584],[7.826042175292968,47.24427960201268],[7.828102111816407,47.25966018070071],[7.82398223876953,47.26548499105541],[7.8408050537109375,47.273405704663965],[7.848701477050781,47.28551744450745],[7.860374450683594,47.30461109337307],[7.871704101562499,47.31136207506936],[7.8888702392578125,47.31136207506936],[7.897453308105469,47.31904317780638],[7.895393371582031,47.327653995607086],[7.908439636230469,47.340451266106996],[7.9259490966796875,47.332773275955894],[7.94757843017578,47.331609846720866],[7.94757843017578,47.316715688820764],[8.007316589355467,47.33905535093827],[8.004913330078125,47.34533667855891],[8.011093139648438,47.35719936945847],[8.024139404296875,47.36719917429931],[8.032722473144531,47.38393878966209],[8.026885986328125,47.39602520707679],[8.010749816894531,47.3955603961201],[8.004570007324219,47.40671472747142],[7.975730895996094,47.41507892620099],[7.9657745361328125,47.42181578692778],[7.985343933105469,47.425764580393924],[7.971954345703124,47.46105827584221],[7.957534790039062,47.457344265054225],[7.940711975097656,47.46221885041022],[7.946891784667968,47.48403288391224],[7.907066345214844,47.48588897929538],[7.8936767578125,47.50653361720931],[7.873420715332031,47.51325876844644],[7.875480651855468,47.52253342509336],[7.865180969238281,47.51975120023913],[7.856254577636718,47.533660849056794],[7.833251953125,47.5325018525392],[7.834281921386719,47.51465007145751],[7.789649963378906,47.49377665301097],[7.789649963378906,47.518128167602484],[7.7515411376953125,47.52461999690649],[7.731285095214843,47.53203824675999],[7.708969116210937,47.54015075619555],[7.740898132324219,47.54362716173679],[7.761497497558593,47.54895720250044],[7.781410217285156,47.55289644950155],[7.797546386718749,47.55915229204993],[7.805442810058593,47.56563904359584],[7.814369201660155,47.575136052077276],[7.819175720214843,47.58648387645128],[7.8325653076171875,47.586715439092906],[7.843208312988281,47.581620824334166],[7.859344482421875,47.58602074809481],[7.8847503662109375,47.58764167941513],[7.903633117675781,47.58092606572345],[7.911872863769532,47.56749225365282],[7.90740966796875,47.55776216936179],[7.917709350585938,47.545712894408624],[7.929382324218749,47.54640812019053],[7.941741943359374,47.54432241518175],[7.9520416259765625,47.54965238525127],[7.9561614990234375,47.55683540041267],[7.9767608642578125,47.55544521625339],[7.997360229492187,47.556603705614094],[8.019676208496094,47.54965238525127],[8.049888610839844,47.55637200979099],[8.058815002441406,47.56285910557121],[8.072891235351562,47.56355410390809],[8.086967468261719,47.557067094186735],[8.100700378417969,47.56216409801383],[8.105506896972656,47.57976811421671],[8.113059997558594,47.583473468887405],[8.133659362792969,47.58301031389572],[8.138809204101562,47.59042030203756],[8.15185546875,47.59551406038282],[8.166275024414062,47.5941249027327],[8.177261352539062,47.6017648134425],[8.193740844726562,47.616346999837226],[8.2012939453125,47.62120682516921],[8.219490051269531,47.61958693358351],[8.223953247070312,47.61102381568743],[8.222923278808594,47.604774168947614]]],"terms_text":"AGIS OF2014","best":true},{"name":"Kanton Basel-Stadt 2015","type":"tms","template":"http://mapproxy.osm.ch:8080/tiles/KTBASELSTADT2015/EPSG900913/{z}/{x}/{y}.png?origin=nw","scaleExtent":[8,21],"polygon":[[[7.492,47.4817],[7.492,47.6342],[7.784,47.6342],[7.784,47.4817],[7.492,47.4817]]],"terms_text":"Kanton Basel-Stadt OF 2015"},{"name":"Kanton Solothurn 25cm (SOGIS 2014-2015)","type":"tms","template":"http://mapproxy.osm.ch:8080/tiles/sogis2014/EPSG900913/{z}/{x}/{y}.png?origin=nw","scaleExtent":[12,19],"polygon":[[[7.3404127,47.2175697],[7.4154818,47.2402115],[7.4173645,47.2537956],[7.4658424,47.2646513],[7.4946766,47.2882287],[7.5328638,47.294534],[7.5483333,47.3163566],[7.5709479,47.3263111],[7.5604584,47.342492],[7.5388991,47.3476266],[7.5396485,47.3601134],[7.5217459,47.3651488],[7.5237238,47.3720704],[7.4634937,47.3702566],[7.4361035,47.3781317],[7.4434011,47.4023143],[7.4774682,47.4012772],[7.4792364,47.3897076],[7.5022557,47.384807],[7.5213659,47.3912021],[7.5311724,47.4035251],[7.5252352,47.4116329],[7.5807413,47.414704],[7.5682954,47.4223349],[7.5689044,47.436897],[7.5812069,47.4287807],[7.6157989,47.4327479],[7.6260723,47.4629139],[7.6044949,47.4704455],[7.6072998,47.4893984],[7.640966,47.4827341],[7.6559259,47.4873946],[7.6521711,47.4958144],[7.6661209,47.4968682],[7.6683266,47.4863467],[7.699761,47.4806325],[7.709878,47.4693848],[7.6848538,47.4478436],[7.6798021,47.417514],[7.6327228,47.4100311],[7.633317,47.382914],[7.6417611,47.3804694],[7.6442033,47.3672084],[7.7279138,47.3688589],[7.751519,47.3443275],[7.7935609,47.3390523],[7.8021665,47.3610959],[7.8788122,47.3835105],[7.8691367,47.3955143],[7.883332,47.4060973],[7.9097377,47.398521],[7.9550377,47.4156057],[7.9618317,47.4218343],[7.9467846,47.4431934],[7.9682836,47.4628082],[7.9872707,47.4287435],[7.9854653,47.4227641],[7.9827035,47.4283325],[7.9631993,47.4223547],[8.0072617,47.4065858],[8.0100022,47.395418],[8.0265612,47.3956224],[8.0313669,47.3836856],[8.0038366,47.3453146],[8.0051906,47.3367516],[7.9479701,47.3171432],[7.9478307,47.3325169],[7.9192088,47.3339507],[7.9078055,47.341719],[7.889098,47.3114878],[7.8611018,47.3061239],[7.8418057,47.2744707],[7.8166423,47.2616706],[7.8028241,47.2684079],[7.7861469,47.256098],[7.7746009,47.267869],[7.7568187,47.258095],[7.7326672,47.2591133],[7.684769,47.2939919],[7.6482742,47.2819898],[7.5801066,47.2763483],[7.5936981,47.2662199],[7.5959384,47.245569],[7.6261802,47.2263143],[7.6405558,47.2297944],[7.6484666,47.2189525],[7.6472258,47.2017823],[7.6715278,47.1949714],[7.6711002,47.1845216],[7.6779881,47.1819259],[7.6728612,47.1683945],[7.6600808,47.1684026],[7.6451021,47.1489207],[7.6155322,47.1565739],[7.5861404,47.1475453],[7.5810534,47.16013],[7.5634674,47.1683541],[7.5257686,47.162205],[7.5203336,47.1588879],[7.5297508,47.1487369],[7.5097234,47.1255457],[7.4613252,47.1082327],[7.4750945,47.0867101],[7.454461,47.074927],[7.4354156,47.0801664],[7.4340002,47.1005003],[7.3820271,47.0957398],[7.3704914,47.1209312],[7.4401788,47.1237276],[7.4217922,47.1358605],[7.447783,47.1550805],[7.4728074,47.1525609],[7.4970383,47.1700873],[7.4804964,47.171738],[7.4708545,47.181324],[7.4757226,47.1906485],[7.4497638,47.1895691],[7.4476258,47.1810839],[7.4332849,47.1847269],[7.4118135,47.1624212],[7.3842442,47.1601249],[7.3821749,47.1651186],[7.391911,47.1662739],[7.3835137,47.1803011],[7.3654609,47.1944525],[7.3544799,47.1915316],[7.3404127,47.2175697]],[[7.420816,47.4803666],[7.4349836,47.4981011],[7.4707584,47.480734],[7.487277,47.4820136],[7.5116652,47.5026958],[7.5317892,47.4973989],[7.5366964,47.4850517],[7.5274454,47.4739062],[7.5306791,47.4611886],[7.4565122,47.4492558],[7.445214,47.4623781],[7.4557367,47.4733767],[7.420816,47.4803666]],[[7.3759458,47.4140995],[7.3821514,47.4330266],[7.4209041,47.4459442],[7.4378427,47.4463232],[7.4555765,47.4279232],[7.4437574,47.413444],[7.3759458,47.4140995]],[[7.6744234,47.1539707],[7.6853662,47.1662986],[7.7007985,47.1617746],[7.6901531,47.1525567],[7.6744234,47.1539707]]],"terms_text":"Orthofoto WMS Solothurn","best":true},{"name":"Kanton Zürich 2015  10cm","type":"tms","template":"http://mapproxy.osm.ch:8080/tiles/KTZUERICH2015/EPSG900913/{z}/{x}/{y}.png?origin=nw","scaleExtent":[8,21],"polygon":[[[8.807601928710938,47.66608099332474],[8.808631896972656,47.65475043477393],[8.830604553222656,47.648506014952225],[8.805885314941406,47.597597727711346],[8.749580383300781,47.61565270219988],[8.751983642578125,47.59505101193038],[8.807945251464844,47.585789182379905],[8.811721801757812,47.57467282332527],[8.840904235839844,47.57467282332527],[8.854637145996094,47.56216409801383],[8.8330078125,47.55382328811835],[8.845024108886719,47.53458802782819],[8.899612426757812,47.52786561031842],[8.895835876464844,47.491224888201955],[8.902702331542969,47.48588897929538],[8.887252807617188,47.475911695481756],[8.911285400390625,47.43969913094723],[8.934288024902344,47.43807362350206],[8.935317993164062,47.43017758727173],[8.917121887207031,47.42808726171425],[8.909912109375,47.404855836246135],[8.944587707519531,47.38905261221537],[8.945274353027344,47.379521907289295],[8.963127136230469,47.357664518690434],[8.973083496093748,47.35580389715929],[8.989906311035156,47.31857768821123],[8.973426818847656,47.30367985581531],[8.9593505859375,47.300653220457775],[8.941154479980469,47.2873805430142],[8.950080871582031,47.28458587064588],[8.940467834472656,47.259194168186234],[8.876266479492188,47.24847474828181],[8.876609802246092,47.243114224640834],[8.850173950195312,47.23961793870555],[8.849830627441406,47.247076403108416],[8.825111389160156,47.24824169331652],[8.800048828125,47.24031721435106],[8.804855346679688,47.23425651880584],[8.815155029296875,47.217702626593784],[8.793525695800781,47.21886856286133],[8.71490478515625,47.20021050593422],[8.685722351074219,47.18154588528182],[8.697395324707031,47.163108130899104],[8.660659790039062,47.15633823511178],[8.6572265625,47.16684287656919],[8.618087768554688,47.172444502751944],[8.622550964355469,47.17991241867412],[8.607101440429688,47.201376826785406],[8.595085144042969,47.19834433924206],[8.575859069824219,47.21513747655813],[8.541183471679688,47.2186353776589],[8.471488952636719,47.2053421258966],[8.441619873046875,47.22120035848172],[8.417243957519531,47.22120035848172],[8.383941650390625,47.292270864380086],[8.422050476074219,47.302282968719936],[8.442306518554688,47.32439601339355],[8.413810729980469,47.32299967378833],[8.408660888671875,47.33067908487908],[8.378448486328125,47.39718721653071],[8.360939025878906,47.39695481668995],[8.359222412109375,47.4053205652024],[8.379135131835938,47.40764414848437],[8.377418518066406,47.41624051540972],[8.384284973144531,47.42274494145051],[8.372611999511719,47.42808726171425],[8.372955322265625,47.437376962080776],[8.379478454589844,47.45037978769006],[8.36402893066406,47.46198673754625],[8.352012634277344,47.5079250985124],[8.373985290527344,47.517200697839414],[8.392181396484375,47.5366741201253],[8.417587280273436,47.56610235225701],[8.430290222167967,47.5693453981427],[8.491744995117188,47.581620824334166],[8.487625122070312,47.58648387645128],[8.463935852050781,47.58301031389572],[8.453292846679688,47.60315376826432],[8.479385375976562,47.617504142079596],[8.505821228027344,47.61958693358351],[8.513717651367188,47.635783590864854],[8.542213439941406,47.632776019724375],[8.545646667480469,47.627685889602006],[8.564186096191406,47.6256034207548],[8.566932678222656,47.61935551640258],[8.576202392578125,47.613569753973955],[8.564872741699219,47.60037582174319],[8.535346984863281,47.586715439092906],[8.550109863281248,47.5714301073211],[8.555259704589844,47.55498181333744],[8.581008911132812,47.59551406038282],[8.598861694335936,47.61449551898437],[8.59130859375,47.64642437575518],[8.609848022460938,47.65521295468833],[8.620834350585938,47.646886969413],[8.618431091308594,47.65660048985082],[8.602981567382812,47.666312203609145],[8.610877990722656,47.67856488312544],[8.62323760986328,47.67856488312544],[8.621864318847656,47.69312564683551],[8.64898681640625,47.697516190510555],[8.667526245117188,47.68665469810477],[8.671646118164062,47.67602211074509],[8.692245483398438,47.65197522925437],[8.734817504882812,47.64526787368664],[8.777389526367188,47.65313158281113],[8.785629272460938,47.667930646923494],[8.807601928710938,47.66608099332474]]],"terms_text":"Kanton Zürich OF 2015","best":true},{"name":"Katastrálna mapa Slovenska (KaPor, 2010-04)","type":"tms","template":"http://www.freemap.sk/tms/kapor2/{zoom}/{x}/{y}.jpg","polygon":[[[19.83682,49.25529],[19.80075,49.42385],[19.60437,49.48058],[19.49179,49.63961],[19.21831,49.52604],[19.16778,49.42521],[19.00308,49.42236],[18.97611,49.5308],[18.54685,49.51425],[18.31432,49.33818],[18.15913,49.2961],[18.05564,49.11134],[17.56396,48.84938],[17.17929,48.88816],[17.058,48.81105],[16.90426,48.61947],[16.79685,48.38561],[17.06762,48.01116],[17.32787,47.97749],[17.51699,47.82535],[17.74776,47.73093],[18.29515,47.72075],[18.67959,47.75541],[18.89755,47.81203],[18.79463,47.88245],[18.84318,48.04046],[19.46212,48.05333],[19.62064,48.22938],[19.89585,48.09387],[20.33766,48.2643],[20.55395,48.52358],[20.82335,48.55714],[21.10271,48.47096],[21.45863,48.55513],[21.74536,48.31435],[22.15293,48.37179],[22.61255,49.08914],[22.09997,49.23814],[21.9686,49.36363],[21.6244,49.46989],[21.06873,49.46402],[20.94336,49.31088],[20.73052,49.44006],[20.22804,49.41714],[20.05234,49.23052],[19.83682,49.25529]]],"terms_url":"http://wiki.freemap.sk/KatasterPortal","terms_text":"Permisssion by UGKK"},{"name":"Katastrálna mapa Slovenska (KaPor, 2011-05)","type":"tms","template":"http://www.freemap.sk/tms/kapor2_201105/{zoom}/{x}/{y}.jpg","polygon":[[[19.83682,49.25529],[19.80075,49.42385],[19.60437,49.48058],[19.49179,49.63961],[19.21831,49.52604],[19.16778,49.42521],[19.00308,49.42236],[18.97611,49.5308],[18.54685,49.51425],[18.31432,49.33818],[18.15913,49.2961],[18.05564,49.11134],[17.56396,48.84938],[17.17929,48.88816],[17.058,48.81105],[16.90426,48.61947],[16.79685,48.38561],[17.06762,48.01116],[17.32787,47.97749],[17.51699,47.82535],[17.74776,47.73093],[18.29515,47.72075],[18.67959,47.75541],[18.89755,47.81203],[18.79463,47.88245],[18.84318,48.04046],[19.46212,48.05333],[19.62064,48.22938],[19.89585,48.09387],[20.33766,48.2643],[20.55395,48.52358],[20.82335,48.55714],[21.10271,48.47096],[21.45863,48.55513],[21.74536,48.31435],[22.15293,48.37179],[22.61255,49.08914],[22.09997,49.23814],[21.9686,49.36363],[21.6244,49.46989],[21.06873,49.46402],[20.94336,49.31088],[20.73052,49.44006],[20.22804,49.41714],[20.05234,49.23052],[19.83682,49.25529]]],"terms_url":"http://wiki.freemap.sk/KatasterPortal","terms_text":"Permisssion by UGKK"},{"name":"Kelowna 2012","type":"tms","description":"High quality aerial imagery taken for the City of Kelowna","template":"http://{switch:a,b,c,d}.tile.paulnorman.ca/kelowna2012/{zoom}/{x}/{y}.png","scaleExtent":[9,20],"polygon":[[[-119.5867318,49.7928087],[-119.5465655,49.7928097],[-119.5465661,49.8013837],[-119.5343374,49.8013841],[-119.5343376,49.8047321],[-119.5296211,49.8047322],[-119.5296216,49.8119555],[-119.5104463,49.811956],[-119.5115683,49.8744325],[-119.5108946,49.8744904],[-119.5114111,49.8843312],[-119.5114115,49.9221763],[-119.49386,49.9223477],[-119.4940505,49.9313031],[-119.4803936,49.9317529],[-119.4804572,49.9407474],[-119.4666732,49.9409927],[-119.4692775,49.9913717],[-119.4551337,49.9916078],[-119.4556736,50.0121242],[-119.4416673,50.0123895],[-119.4417308,50.0136345],[-119.4221492,50.0140377],[-119.4221042,50.0119306],[-119.4121303,50.012165],[-119.4126082,50.0216913],[-119.4123387,50.0216913],[-119.4124772,50.0250773],[-119.4120917,50.0250821],[-119.4121954,50.0270769],[-119.4126083,50.0270718],[-119.4128328,50.0321946],[-119.3936313,50.0326418],[-119.393529,50.0307781],[-119.3795727,50.0310116],[-119.3795377,50.0287584],[-119.3735764,50.0288621],[-119.371544,49.9793618],[-119.3573506,49.9793618],[-119.3548353,49.9256081],[-119.3268079,49.9257238],[-119.3256573,49.8804068],[-119.3138893,49.8806528],[-119.3137097,49.8771651],[-119.3132156,49.877223],[-119.3131482,49.8749652],[-119.312452,49.8749073],[-119.3122275,49.87236],[-119.3117558,49.872331],[-119.3115986,49.8696098],[-119.3112169,49.8694217],[-119.3109199,49.8632417],[-119.3103721,49.8632724],[-119.3095139,49.8512388],[-119.3106368,49.8512316],[-119.3103859,49.8462564],[-119.3245344,49.8459957],[-119.3246018,49.8450689],[-119.3367018,49.844875],[-119.3367467,49.8435136],[-119.337937,49.8434702],[-119.3378023,49.8382055],[-119.3383637,49.8381041],[-119.3383749,49.8351202],[-119.3390936,49.8351058],[-119.3388016,49.8321217],[-119.3391497,49.8320565],[-119.3391722,49.8293331],[-119.3394641,49.8293331],[-119.3395879,49.8267878],[-119.3500053,49.8265829],[-119.3493701,49.8180588],[-119.4046964,49.8163785],[-119.4045694,49.8099022],[-119.4101592,49.8099022],[-119.4102862,49.8072787],[-119.4319467,49.8069098],[-119.4322643,49.7907965],[-119.4459847,49.7905504],[-119.445286,49.7820201],[-119.4967376,49.7811587],[-119.4966105,49.7784927],[-119.5418371,49.7775082],[-119.5415892,49.7718277],[-119.5560296,49.7714941],[-119.5561194,49.7718422],[-119.5715704,49.7715086],[-119.5716153,49.7717262],[-119.5819235,49.7714941],[-119.5820133,49.7717697],[-119.5922991,49.7715231],[-119.592344,49.7718132],[-119.6003839,49.7715957],[-119.6011924,49.7839081],[-119.5864365,49.7843863],[-119.5867318,49.7928087]]],"id":"kelowna_2012"},{"name":"Kelowna Roads overlay","type":"tms","template":"http://{switch:a,b,c,d}.tile.paulnorman.ca/kelowna_overlay/{zoom}/{x}/{y}.png","scaleExtent":[9,20],"polygon":[[[-119.5867318,49.7928087],[-119.5465655,49.7928097],[-119.5465661,49.8013837],[-119.5343374,49.8013841],[-119.5343376,49.8047321],[-119.5296211,49.8047322],[-119.5296216,49.8119555],[-119.5104463,49.811956],[-119.5115683,49.8744325],[-119.5108946,49.8744904],[-119.5114111,49.8843312],[-119.5114115,49.9221763],[-119.49386,49.9223477],[-119.4940505,49.9313031],[-119.4803936,49.9317529],[-119.4804572,49.9407474],[-119.4666732,49.9409927],[-119.4692775,49.9913717],[-119.4551337,49.9916078],[-119.4556736,50.0121242],[-119.4416673,50.0123895],[-119.4417308,50.0136345],[-119.4221492,50.0140377],[-119.4221042,50.0119306],[-119.4121303,50.012165],[-119.4126082,50.0216913],[-119.4123387,50.0216913],[-119.4124772,50.0250773],[-119.4120917,50.0250821],[-119.4121954,50.0270769],[-119.4126083,50.0270718],[-119.4128328,50.0321946],[-119.3936313,50.0326418],[-119.393529,50.0307781],[-119.3795727,50.0310116],[-119.3795377,50.0287584],[-119.3735764,50.0288621],[-119.371544,49.9793618],[-119.3573506,49.9793618],[-119.3548353,49.9256081],[-119.3268079,49.9257238],[-119.3256573,49.8804068],[-119.3138893,49.8806528],[-119.3137097,49.8771651],[-119.3132156,49.877223],[-119.3131482,49.8749652],[-119.312452,49.8749073],[-119.3122275,49.87236],[-119.3117558,49.872331],[-119.3115986,49.8696098],[-119.3112169,49.8694217],[-119.3109199,49.8632417],[-119.3103721,49.8632724],[-119.3095139,49.8512388],[-119.3106368,49.8512316],[-119.3103859,49.8462564],[-119.3245344,49.8459957],[-119.3246018,49.8450689],[-119.3367018,49.844875],[-119.3367467,49.8435136],[-119.337937,49.8434702],[-119.3378023,49.8382055],[-119.3383637,49.8381041],[-119.3383749,49.8351202],[-119.3390936,49.8351058],[-119.3388016,49.8321217],[-119.3391497,49.8320565],[-119.3391722,49.8293331],[-119.3394641,49.8293331],[-119.3395879,49.8267878],[-119.3500053,49.8265829],[-119.3493701,49.8180588],[-119.4046964,49.8163785],[-119.4045694,49.8099022],[-119.4101592,49.8099022],[-119.4102862,49.8072787],[-119.4319467,49.8069098],[-119.4322643,49.7907965],[-119.4459847,49.7905504],[-119.445286,49.7820201],[-119.4967376,49.7811587],[-119.4966105,49.7784927],[-119.5418371,49.7775082],[-119.5415892,49.7718277],[-119.5560296,49.7714941],[-119.5561194,49.7718422],[-119.5715704,49.7715086],[-119.5716153,49.7717262],[-119.5819235,49.7714941],[-119.5820133,49.7717697],[-119.5922991,49.7715231],[-119.592344,49.7718132],[-119.6003839,49.7715957],[-119.6011924,49.7839081],[-119.5864365,49.7843863],[-119.5867318,49.7928087]]],"id":"kelowna_roads","overlay":true},{"name":"Landsat 233055","type":"tms","description":"Recent Landsat imagery","template":"http://{switch:a,b,c,d}.tile.paulnorman.ca/landsat_233055/{zoom}/{x}/{y}.png","scaleExtent":[5,14],"polygon":[[[-60.8550011,6.1765004],[-60.4762612,7.9188291],[-62.161689,8.2778675],[-62.5322549,6.5375488],[-60.8550011,6.1765004]]],"id":"landsat_233055"},{"name":"Latest southwest British Columbia Landsat","type":"tms","description":"Recent lower-resolution landsat imagery for southwest British Columbia","template":"http://{switch:a,b,c,d}.tile.paulnorman.ca/landsat_047026/{zoom}/{x}/{y}.png","scaleExtent":[5,13],"polygon":[[[-121.9355512,47.7820648],[-121.5720582,48.6410125],[-121.2015461,49.4846247],[-121.8375516,49.6023246],[-122.4767046,49.7161735],[-123.118912,49.8268824],[-123.760228,49.9335836],[-124.0887706,49.0870469],[-124.4128889,48.2252567],[-123.792772,48.1197334],[-123.1727942,48.0109592],[-122.553553,47.8982299],[-121.9355512,47.7820648]]],"id":"landsat_047026"},{"name":"Lithuania - NŽT ORT10LT","type":"tms","template":"http://mapproxy.openmap.lt/ort10lt/g/{z}/{x}/{y}.jpeg","scaleExtent":[4,18],"polygon":[[[21.4926054,56.3592046],[21.8134688,56.4097144],[21.9728753,56.4567587],[22.2158294,56.4604404],[22.2183922,56.4162361],[23.3511527,56.4267251],[23.3521778,56.3824815],[23.9179035,56.383305],[23.9176231,56.3392908],[24.5649817,56.3382169],[24.564933,56.3828587],[24.6475683,56.4277798],[24.8099394,56.470646],[24.9733979,56.4698452],[25.1299701,56.2890356],[25.127433,56.1990144],[25.6921076,56.1933684],[26.0839005,56.0067879],[26.4673573,55.7304232],[26.5463565,55.7132705],[26.5154447,55.2345969],[25.7874641,54.8425656],[25.7675259,54.6350898],[25.6165253,54.4404007],[24.4566043,53.9577649],[23.6164786,53.9575517],[23.5632006,54.048085],[22.8462074,54.3563682],[22.831944,54.9414849],[22.4306085,55.1159913],[21.9605898,55.1107144],[21.7253241,55.1496885],[21.5628422,55.2362913],[21.2209638,55.2742668],[21.1630444,55.2803979],[20.9277788,55.3101641],[20.9257285,55.3588507],[20.9980451,55.4514157],[21.0282249,56.0796297],[21.4926054,56.3592046]]],"terms_url":"http://www.geoportal.lt","terms_text":"NŽT ORT10LT"},{"name":"Locator Overlay","type":"tms","description":"Shows major features to help orient you.","template":"http://{switch:a,b,c}.tiles.mapbox.com/v4/openstreetmap.map-inh76ba2/{zoom}/{x}/{y}.png?access_token=pk.eyJ1Ijoib3BlbnN0cmVldG1hcCIsImEiOiJncjlmd0t3In0.DmZsIeOW-3x-C5eX-wAqTw","scaleExtent":[0,16],"overzoom":false,"terms_url":"http://www.mapbox.com/about/maps/","terms_text":"Terms & Feedback","default":true,"overlay":true},{"name":"LPI NSW Base Map","type":"tms","template":"http://maps.six.nsw.gov.au/arcgis/rest/services/public/NSW_Base_Map/MapServer/tile/{zoom}/{y}/{x}","scaleExtent":[0,19],"polygon":[[[140.9948644,-28.952966],[148.9611382,-28.8997729],[148.9870097,-28.4862285],[151.013609,-28.4786485],[151.1084711,-28.7032909],[151.8759917,-28.683118],[151.9334839,-28.4078753],[152.25544,-28.2332683],[153.0660798,-28.2104723],[153.1408196,-28.1090981],[153.4735137,-28.1164808],[153.3576523,-27.693606],[159.4938303,-27.699252],[159.4856997,-37.8474137],[149.5256879,-37.8281502],[149.9159578,-37.4869999],[148.0485886,-36.8131741],[147.9680996,-36.1567945],[146.7147701,-36.2866613],[145.3004625,-36.1567945],[144.5300673,-36.1475101],[142.8397973,-35.0254303],[142.356863,-34.7802471],[141.9774146,-34.4016159],[140.9950258,-34.1371824],[140.9948644,-28.952966]]],"terms_url":"http://spatialservices.finance.nsw.gov.au/mapping_and_imagery/lpi_web_services","terms_text":"© Land and Property Information 2016","id":"NSW LPI Base Map"},{"name":"LPI NSW Imagery","type":"tms","template":"http://maps.six.nsw.gov.au/arcgis/rest/services/public/NSW_Imagery/MapServer/tile/{zoom}/{y}/{x}","scaleExtent":[0,21],"polygon":[[[140.9868688,-28.9887829],[148.9951472,-28.9727491],[148.9966717,-28.4915066],[151.0029027,-28.4930697],[151.0029027,-28.7261663],[151.4915093,-28.7323921],[151.4918687,-28.7155337],[151.9228213,-28.719635],[151.9251607,-28.4897139],[151.9955886,-28.4898718],[151.9989947,-28.1192742],[152.4967606,-28.122091],[152.4968241,-28.1146398],[153.0044563,-28.1154389],[153.0044563,-28.120397],[153.5038629,-28.119345],[153.5039264,-28.1227063],[153.5919395,-28.1223619],[153.5926582,-28.1776872],[153.6111186,-28.1757867],[153.6113881,-28.1825173],[153.7426846,-28.2162084],[153.7787253,-28.710911],[152.6237954,-32.5877239],[152.3123961,-32.6328837],[151.4141942,-33.5790388],[150.8929925,-35.2648721],[150.4620695,-35.7777256],[150.0156501,-37.5103569],[149.9918121,-37.5126787],[149.519778,-37.5130704],[149.5199577,-37.5216919],[149.4462958,-37.5353701],[149.063344,-37.5357975],[148.9836635,-37.5217631],[148.9816872,-37.5191982],[148.9863847,-37.2584972],[148.4875376,-37.265846],[148.4824774,-37.0092669],[147.994386,-37.014339],[147.988288,-36.5332184],[147.9529707,-36.5260725],[147.9486513,-36.0685992],[147.5034997,-36.0716798],[147.5047701,-36.2651047],[146.4919996,-36.266129],[146.4922536,-36.2565],[145.9929826,-36.2534267],[145.9965866,-36.0188147],[145.9831568,-36.0187058],[145.9624506,-36.0219026],[145.946236,-36.0120936],[145.9454275,-36.0060259],[145.5041534,-36.0013564],[145.5037941,-36.0109125],[145.0072008,-36.0036213],[145.0035404,-36.1520424],[144.4860806,-36.1423149],[144.4874127,-36.0137522],[143.9874676,-36.0024134],[143.9932853,-35.5723753],[143.4971691,-35.5837101],[143.4917967,-35.4065648],[143.4613438,-35.3674934],[143.4585591,-35.3555888],[143.4897755,-35.3396522],[143.4895509,-35.332214],[143.4316994,-35.2570613],[143.2505542,-35.2606556],[143.2438356,-35.0132729],[142.9933305,-35.0177207],[142.9919767,-34.7961882],[142.4971375,-34.8032323],[142.4973172,-34.8007613],[142.4211401,-34.8017571],[142.4209155,-34.7838306],[142.2330892,-34.7859191],[142.2307707,-34.7807542],[142.2269959,-34.5061271],[141.9975302,-34.5083733],[141.9945959,-34.2526687],[141.4982345,-34.2556921],[141.498171,-34.2522794],[140.9945397,-34.2528411],[140.9868688,-28.9887829]]],"terms_url":"http://spatialservices.finance.nsw.gov.au/mapping_and_imagery/lpi_web_services","terms_text":"© Land and Property Information 2016","id":"NSW LPI Imagery","best":true},{"name":"LPI NSW Topographic Map","type":"tms","template":"http://maps.six.nsw.gov.au/arcgis/rest/services/public/NSW_Topo_Map/MapServer/tile/{zoom}/{y}/{x}","scaleExtent":[0,16],"polygon":[[[140.9988422,-28.9992444],[148.9502438,-28.9993736],[148.9498845,-28.9665265],[148.9998308,-28.9665265],[149.0000917,-28.8165829],[149.1000729,-28.8165829],[149.0997046,-28.7488533],[148.9998504,-28.7497444],[148.9998169,-28.5000304],[151.0000514,-28.5005192],[151.0005904,-28.7325849],[151.0239466,-28.7327424],[151.0241262,-28.7418794],[151.0329297,-28.7418794],[151.033828,-28.7505431],[151.999984,-28.7495314],[151.999984,-28.7164478],[152.0334014,-28.7166053],[152.0332217,-28.683196],[152.0000739,-28.6833537],[151.9998769,-28.6416273],[151.9829886,-28.6413908],[151.9831683,-28.624912],[151.9331321,-28.6247543],[151.9334122,-28.500071],[151.9998875,-28.5002289],[151.9998556,-28.3749591],[152.2499739,-28.3750718],[152.2499356,-28.2500066],[152.9997192,-28.2498563],[152.9998989,-28.2832447],[153.1165002,-28.2834029],[153.11659,-28.2498563],[153.1666262,-28.2500146],[153.166716,-28.2331582],[153.2499898,-28.2332373],[153.2500265,-28.1249689],[153.6249628,-28.1250833],[153.6248398,-28.4999134],[153.7497955,-28.4999924],[153.7495877,-28.7497976],[153.6248117,-28.7501127],[153.6249745,-28.9999333],[153.4997672,-29.0000612],[153.4998417,-29.4995077],[153.3747962,-29.500055],[153.3754111,-29.8750302],[153.4999113,-29.8751403],[153.4999113,-30.0000922],[153.2498947,-29.9997621],[153.250025,-30.1917704],[153.2748185,-30.1916151],[153.2748185,-30.2168467],[153.2166077,-30.2166139],[153.2166077,-30.250065],[153.250025,-30.250065],[153.2497502,-30.3751935],[153.1243608,-30.3749743],[153.1246457,-30.6250359],[153.0331676,-30.6250482],[153.0333884,-30.8750837],[153.1249214,-30.8750291],[153.1249344,-31.1250505],[153.0082433,-31.1249736],[153.0082914,-31.2499759],[153.0000019,-31.250003],[152.9999392,-31.6249919],[152.8749386,-31.6250491],[152.8749572,-31.749954],[152.7832899,-31.7500034],[152.7831966,-31.8748579],[152.749914,-31.8750105],[152.7500397,-32.0000207],[152.6249044,-31.9999446],[152.6249078,-32.5000047],[152.4999757,-32.4999569],[152.5000336,-32.5666443],[152.4166699,-32.5663415],[152.4167598,-32.6249954],[152.3498477,-32.624991],[152.3498477,-32.6332294],[152.2830786,-32.6332218],[152.2832583,-32.6249755],[152.2494816,-32.6249755],[152.2498101,-32.874906],[151.8745693,-32.8750443],[151.8748535,-33.0000091],[151.7497706,-33.0001533],[151.7504669,-33.2500398],[151.6252418,-33.2497393],[151.6250828,-33.3751621],[151.499585,-33.3751442],[151.5003127,-33.6249385],[151.3741466,-33.6243658],[151.3727902,-34.001962],[151.2477819,-34.0011194],[151.2477819,-34.2493114],[150.9957327,-34.2501515],[151.0008143,-34.62483],[150.8717407,-34.6265026],[150.872757,-35.1242738],[150.7670589,-35.1234425],[150.7690916,-35.2463774],[150.6257894,-35.2496974],[150.6280314,-35.3751485],[150.4999742,-35.3751485],[150.4959088,-35.6275034],[150.3719169,-35.6250251],[150.3749658,-35.7537957],[150.2672351,-35.7513213],[150.2652024,-35.8741232],[150.2479249,-35.870829],[150.2458922,-36.374885],[150.1229166,-36.374885],[150.1259656,-36.6224345],[150.0253491,-36.6240658],[150.0283981,-36.7471337],[149.9928266,-36.7495768],[150.0040062,-37.1224477],[150.0588879,-37.1273097],[150.0568553,-37.37809],[149.9979083,-37.3732441],[149.9999409,-37.4830073],[149.987745,-37.4846202],[149.9857123,-37.5080043],[148.0684571,-36.80624],[147.9930603,-36.1379955],[147.8148345,-36.0055567],[147.3893924,-36.0113701],[147.3822059,-36.1310306],[146.9972549,-36.1275479],[146.9886311,-36.2528271],[146.4956356,-36.2447132],[146.5042595,-36.126387],[145.0011817,-36.0079505],[145.0154103,-36.2542074],[144.5072465,-36.2476506],[144.4991158,-36.0211037],[143.9965422,-35.9810531],[143.3382568,-35.2331794],[142.4097581,-34.7669434],[142.0361436,-34.3758837],[140.9965216,-34.1385805],[140.9988422,-28.9992444]]],"terms_url":"http://spatialservices.finance.nsw.gov.au/mapping_and_imagery/lpi_web_services","terms_text":"© Land and Property Information 2016","id":"NSW LPI Topographic Map"},{"name":"Luxembourg Geoportail Basemap","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/basemap/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.png","scaleExtent":[0,20],"polygon":[[[5.961753,50.17631],[6.026268,50.18496],[6.033182,50.16395],[6.060695,50.15536],[6.07668,50.15913],[6.078237,50.17255],[6.101762,50.17199],[6.122501,50.16437],[6.120101,50.15594],[6.127695,50.14993],[6.113228,50.13739],[6.123691,50.13719],[6.140929,50.1305],[6.135554,50.11899],[6.138082,50.10263],[6.131085,50.09964],[6.135473,50.09119],[6.121939,50.09059],[6.126335,50.07817],[6.131858,50.07348],[6.121171,50.064],[6.114444,50.06139],[6.115631,50.05817],[6.123611,50.06323],[6.136608,50.04178],[6.130343,50.02975],[6.148207,50.02307],[6.13868,50.01572],[6.135938,50.01485],[6.131384,50.01905],[6.130243,50.01819],[6.139343,50.01116],[6.151702,50.01058],[6.145464,49.99689],[6.139657,49.9994],[6.138524,49.99829],[6.142178,49.99535],[6.150227,49.99518],[6.156247,49.98867],[6.173045,49.98589],[6.17348,49.98344],[6.170353,49.98376],[6.165487,49.97115],[6.171512,49.96298],[6.176298,49.962],[6.179954,49.95386],[6.183393,49.9548],[6.179829,49.96307],[6.183312,49.9686],[6.192774,49.97158],[6.199783,49.95352],[6.207066,49.95672],[6.212689,49.9514],[6.225023,49.95039],[6.22044,49.94369],[6.228241,49.93726],[6.22635,49.92766],[6.219133,49.92354],[6.229862,49.92125],[6.236032,49.91355],[6.231867,49.91064],[6.227694,49.91062],[6.232286,49.9072],[6.23381,49.90028],[6.246919,49.89535],[6.257809,49.88724],[6.263008,49.88101],[6.276455,49.87725],[6.281126,49.87957],[6.291661,49.87548],[6.297699,49.86673],[6.309889,49.87107],[6.315324,49.8673],[6.314651,49.86057],[6.323611,49.85188],[6.321577,49.8409],[6.327406,49.83673],[6.336561,49.83998],[6.339366,49.8507],[6.364651,49.85164],[6.402203,49.82098],[6.426434,49.81629],[6.428071,49.81186],[6.43097,49.81129],[6.441608,49.81547],[6.443442,49.81233],[6.45366,49.81275],[6.464538,49.81975],[6.47057,49.82385],[6.496805,49.81277],[6.50669,49.80993],[6.511554,49.80238],[6.51485,49.80513],[6.519604,49.81446],[6.529808,49.81048],[6.532249,49.80686],[6.530829,49.80116],[6.506225,49.78899],[6.519171,49.78344],[6.511055,49.77422],[6.520563,49.76818],[6.520516,49.76134],[6.503734,49.75086],[6.502627,49.73298],[6.507266,49.72938],[6.518092,49.7242],[6.516417,49.72129],[6.511763,49.72016],[6.504791,49.725],[6.498913,49.72639],[6.495576,49.72443],[6.507122,49.71655],[6.507884,49.71215],[6.504598,49.71227],[6.427139,49.66237],[6.439899,49.66025],[6.442511,49.65591],[6.421781,49.61809],[6.398978,49.60094],[6.379408,49.59526],[6.375507,49.58809],[6.384426,49.5801],[6.381188,49.57509],[6.369093,49.5783],[6.357913,49.57166],[6.384902,49.55817],[6.380095,49.54856],[6.358555,49.53296],[6.359322,49.52481],[6.370763,49.50545],[6.370562,49.45732],[6.333403,49.46493],[6.321894,49.47244],[6.295034,49.47928],[6.287889,49.48379],[6.271912,49.49995],[6.241327,49.50693],[6.196692,49.50331],[6.173373,49.50577],[6.160858,49.50085],[6.167099,49.49006],[6.140179,49.48525],[6.129367,49.48803],[6.127247,49.47081],[6.101403,49.46726],[6.104826,49.45076],[6.081667,49.45417],[6.077222,49.46139],[6.059167,49.46306],[6.052222,49.46028],[6.044213,49.44553],[6.025294,49.44703],[6.021545,49.45127],[6.01574,49.44885],[5.994123,49.45301],[5.976569,49.44885],[5.977725,49.45955],[5.972317,49.46087],[5.968912,49.48202],[5.9616,49.49026],[5.915781,49.49835],[5.890334,49.4948],[5.863321,49.50006],[5.84897,49.50826],[5.84828,49.51397],[5.83641,49.51817],[5.831868,49.52639],[5.84308,49.53081],[5.835622,49.54114],[5.816251,49.53325],[5.805201,49.54272],[5.859432,49.57158],[5.868663,49.587],[5.862888,49.58525],[5.851102,49.58379],[5.847116,49.58961],[5.845652,49.5981],[5.869401,49.6106],[5.881819,49.63815],[5.899978,49.63907],[5.899339,49.66239],[5.856561,49.67628],[5.856283,49.68211],[5.875703,49.71118],[5.864811,49.72331],[5.843249,49.71822],[5.82191,49.72128],[5.824894,49.73767],[5.820728,49.74878],[5.786264,49.79079],[5.765172,49.78961],[5.750937,49.79094],[5.741591,49.82126],[5.745814,49.82435],[5.737197,49.83353],[5.740531,49.84142],[5.747012,49.84048],[5.746237,49.84783],[5.753989,49.84878],[5.740663,49.85152],[5.752288,49.85922],[5.749545,49.87554],[5.775668,49.87438],[5.775053,49.88057],[5.734598,49.89341],[5.733033,49.90285],[5.757834,49.91737],[5.760393,49.93252],[5.770728,49.93711],[5.768783,49.94239],[5.768802,49.96104],[5.786724,49.96816],[5.80524,49.96677],[5.806521,49.97321],[5.831293,49.97995],[5.834616,49.98656],[5.818057,49.99936],[5.815606,50.01437],[5.847923,50.02809],[5.861889,50.04581],[5.850872,50.0563],[5.857809,50.07186],[5.880997,50.08069],[5.891965,50.12041],[5.952856,50.13384],[5.961753,50.17631]]],"terms_url":"https://data.public.lu/en/datasets/carte-de-base-webservices-wms-et-wmts/","terms_text":"Administration du Cadastre et de la Topographie","id":"lu.geoportail.opendata.basemap"},{"name":"Luxembourg Geoportail Cadastre","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/cadastre/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.png","scaleExtent":[0,20],"polygon":[[[5.961753,50.17631],[6.026268,50.18496],[6.033182,50.16395],[6.060695,50.15536],[6.07668,50.15913],[6.078237,50.17255],[6.101762,50.17199],[6.122501,50.16437],[6.120101,50.15594],[6.127695,50.14993],[6.113228,50.13739],[6.123691,50.13719],[6.140929,50.1305],[6.135554,50.11899],[6.138082,50.10263],[6.131085,50.09964],[6.135473,50.09119],[6.121939,50.09059],[6.126335,50.07817],[6.131858,50.07348],[6.121171,50.064],[6.114444,50.06139],[6.115631,50.05817],[6.123611,50.06323],[6.136608,50.04178],[6.130343,50.02975],[6.148207,50.02307],[6.13868,50.01572],[6.135938,50.01485],[6.131384,50.01905],[6.130243,50.01819],[6.139343,50.01116],[6.151702,50.01058],[6.145464,49.99689],[6.139657,49.9994],[6.138524,49.99829],[6.142178,49.99535],[6.150227,49.99518],[6.156247,49.98867],[6.173045,49.98589],[6.17348,49.98344],[6.170353,49.98376],[6.165487,49.97115],[6.171512,49.96298],[6.176298,49.962],[6.179954,49.95386],[6.183393,49.9548],[6.179829,49.96307],[6.183312,49.9686],[6.192774,49.97158],[6.199783,49.95352],[6.207066,49.95672],[6.212689,49.9514],[6.225023,49.95039],[6.22044,49.94369],[6.228241,49.93726],[6.22635,49.92766],[6.219133,49.92354],[6.229862,49.92125],[6.236032,49.91355],[6.231867,49.91064],[6.227694,49.91062],[6.232286,49.9072],[6.23381,49.90028],[6.246919,49.89535],[6.257809,49.88724],[6.263008,49.88101],[6.276455,49.87725],[6.281126,49.87957],[6.291661,49.87548],[6.297699,49.86673],[6.309889,49.87107],[6.315324,49.8673],[6.314651,49.86057],[6.323611,49.85188],[6.321577,49.8409],[6.327406,49.83673],[6.336561,49.83998],[6.339366,49.8507],[6.364651,49.85164],[6.402203,49.82098],[6.426434,49.81629],[6.428071,49.81186],[6.43097,49.81129],[6.441608,49.81547],[6.443442,49.81233],[6.45366,49.81275],[6.464538,49.81975],[6.47057,49.82385],[6.496805,49.81277],[6.50669,49.80993],[6.511554,49.80238],[6.51485,49.80513],[6.519604,49.81446],[6.529808,49.81048],[6.532249,49.80686],[6.530829,49.80116],[6.506225,49.78899],[6.519171,49.78344],[6.511055,49.77422],[6.520563,49.76818],[6.520516,49.76134],[6.503734,49.75086],[6.502627,49.73298],[6.507266,49.72938],[6.518092,49.7242],[6.516417,49.72129],[6.511763,49.72016],[6.504791,49.725],[6.498913,49.72639],[6.495576,49.72443],[6.507122,49.71655],[6.507884,49.71215],[6.504598,49.71227],[6.427139,49.66237],[6.439899,49.66025],[6.442511,49.65591],[6.421781,49.61809],[6.398978,49.60094],[6.379408,49.59526],[6.375507,49.58809],[6.384426,49.5801],[6.381188,49.57509],[6.369093,49.5783],[6.357913,49.57166],[6.384902,49.55817],[6.380095,49.54856],[6.358555,49.53296],[6.359322,49.52481],[6.370763,49.50545],[6.370562,49.45732],[6.333403,49.46493],[6.321894,49.47244],[6.295034,49.47928],[6.287889,49.48379],[6.271912,49.49995],[6.241327,49.50693],[6.196692,49.50331],[6.173373,49.50577],[6.160858,49.50085],[6.167099,49.49006],[6.140179,49.48525],[6.129367,49.48803],[6.127247,49.47081],[6.101403,49.46726],[6.104826,49.45076],[6.081667,49.45417],[6.077222,49.46139],[6.059167,49.46306],[6.052222,49.46028],[6.044213,49.44553],[6.025294,49.44703],[6.021545,49.45127],[6.01574,49.44885],[5.994123,49.45301],[5.976569,49.44885],[5.977725,49.45955],[5.972317,49.46087],[5.968912,49.48202],[5.9616,49.49026],[5.915781,49.49835],[5.890334,49.4948],[5.863321,49.50006],[5.84897,49.50826],[5.84828,49.51397],[5.83641,49.51817],[5.831868,49.52639],[5.84308,49.53081],[5.835622,49.54114],[5.816251,49.53325],[5.805201,49.54272],[5.859432,49.57158],[5.868663,49.587],[5.862888,49.58525],[5.851102,49.58379],[5.847116,49.58961],[5.845652,49.5981],[5.869401,49.6106],[5.881819,49.63815],[5.899978,49.63907],[5.899339,49.66239],[5.856561,49.67628],[5.856283,49.68211],[5.875703,49.71118],[5.864811,49.72331],[5.843249,49.71822],[5.82191,49.72128],[5.824894,49.73767],[5.820728,49.74878],[5.786264,49.79079],[5.765172,49.78961],[5.750937,49.79094],[5.741591,49.82126],[5.745814,49.82435],[5.737197,49.83353],[5.740531,49.84142],[5.747012,49.84048],[5.746237,49.84783],[5.753989,49.84878],[5.740663,49.85152],[5.752288,49.85922],[5.749545,49.87554],[5.775668,49.87438],[5.775053,49.88057],[5.734598,49.89341],[5.733033,49.90285],[5.757834,49.91737],[5.760393,49.93252],[5.770728,49.93711],[5.768783,49.94239],[5.768802,49.96104],[5.786724,49.96816],[5.80524,49.96677],[5.806521,49.97321],[5.831293,49.97995],[5.834616,49.98656],[5.818057,49.99936],[5.815606,50.01437],[5.847923,50.02809],[5.861889,50.04581],[5.850872,50.0563],[5.857809,50.07186],[5.880997,50.08069],[5.891965,50.12041],[5.952856,50.13384],[5.961753,50.17631]]],"terms_url":"https://data.public.lu/en/datasets/plan-cadastral-numerise-pcn-webservices-wms-et-wmts/","terms_text":"Administration du Cadastre et de la Topographie","id":"lu.geoportail.opendata.cadastre"},{"name":"Luxembourg Geoportail Ortho 2010","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/ortho_2010/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.jpeg","scaleExtent":[0,20],"polygon":[[[5.961753,50.17631],[6.026268,50.18496],[6.033182,50.16395],[6.060695,50.15536],[6.07668,50.15913],[6.078237,50.17255],[6.101762,50.17199],[6.122501,50.16437],[6.120101,50.15594],[6.127695,50.14993],[6.113228,50.13739],[6.123691,50.13719],[6.140929,50.1305],[6.135554,50.11899],[6.138082,50.10263],[6.131085,50.09964],[6.135473,50.09119],[6.121939,50.09059],[6.126335,50.07817],[6.131858,50.07348],[6.121171,50.064],[6.114444,50.06139],[6.115631,50.05817],[6.123611,50.06323],[6.136608,50.04178],[6.130343,50.02975],[6.148207,50.02307],[6.13868,50.01572],[6.135938,50.01485],[6.131384,50.01905],[6.130243,50.01819],[6.139343,50.01116],[6.151702,50.01058],[6.145464,49.99689],[6.139657,49.9994],[6.138524,49.99829],[6.142178,49.99535],[6.150227,49.99518],[6.156247,49.98867],[6.173045,49.98589],[6.17348,49.98344],[6.170353,49.98376],[6.165487,49.97115],[6.171512,49.96298],[6.176298,49.962],[6.179954,49.95386],[6.183393,49.9548],[6.179829,49.96307],[6.183312,49.9686],[6.192774,49.97158],[6.199783,49.95352],[6.207066,49.95672],[6.212689,49.9514],[6.225023,49.95039],[6.22044,49.94369],[6.228241,49.93726],[6.22635,49.92766],[6.219133,49.92354],[6.229862,49.92125],[6.236032,49.91355],[6.231867,49.91064],[6.227694,49.91062],[6.232286,49.9072],[6.23381,49.90028],[6.246919,49.89535],[6.257809,49.88724],[6.263008,49.88101],[6.276455,49.87725],[6.281126,49.87957],[6.291661,49.87548],[6.297699,49.86673],[6.309889,49.87107],[6.315324,49.8673],[6.314651,49.86057],[6.323611,49.85188],[6.321577,49.8409],[6.327406,49.83673],[6.336561,49.83998],[6.339366,49.8507],[6.364651,49.85164],[6.402203,49.82098],[6.426434,49.81629],[6.428071,49.81186],[6.43097,49.81129],[6.441608,49.81547],[6.443442,49.81233],[6.45366,49.81275],[6.464538,49.81975],[6.47057,49.82385],[6.496805,49.81277],[6.50669,49.80993],[6.511554,49.80238],[6.51485,49.80513],[6.519604,49.81446],[6.529808,49.81048],[6.532249,49.80686],[6.530829,49.80116],[6.506225,49.78899],[6.519171,49.78344],[6.511055,49.77422],[6.520563,49.76818],[6.520516,49.76134],[6.503734,49.75086],[6.502627,49.73298],[6.507266,49.72938],[6.518092,49.7242],[6.516417,49.72129],[6.511763,49.72016],[6.504791,49.725],[6.498913,49.72639],[6.495576,49.72443],[6.507122,49.71655],[6.507884,49.71215],[6.504598,49.71227],[6.427139,49.66237],[6.439899,49.66025],[6.442511,49.65591],[6.421781,49.61809],[6.398978,49.60094],[6.379408,49.59526],[6.375507,49.58809],[6.384426,49.5801],[6.381188,49.57509],[6.369093,49.5783],[6.357913,49.57166],[6.384902,49.55817],[6.380095,49.54856],[6.358555,49.53296],[6.359322,49.52481],[6.370763,49.50545],[6.370562,49.45732],[6.333403,49.46493],[6.321894,49.47244],[6.295034,49.47928],[6.287889,49.48379],[6.271912,49.49995],[6.241327,49.50693],[6.196692,49.50331],[6.173373,49.50577],[6.160858,49.50085],[6.167099,49.49006],[6.140179,49.48525],[6.129367,49.48803],[6.127247,49.47081],[6.101403,49.46726],[6.104826,49.45076],[6.081667,49.45417],[6.077222,49.46139],[6.059167,49.46306],[6.052222,49.46028],[6.044213,49.44553],[6.025294,49.44703],[6.021545,49.45127],[6.01574,49.44885],[5.994123,49.45301],[5.976569,49.44885],[5.977725,49.45955],[5.972317,49.46087],[5.968912,49.48202],[5.9616,49.49026],[5.915781,49.49835],[5.890334,49.4948],[5.863321,49.50006],[5.84897,49.50826],[5.84828,49.51397],[5.83641,49.51817],[5.831868,49.52639],[5.84308,49.53081],[5.835622,49.54114],[5.816251,49.53325],[5.805201,49.54272],[5.859432,49.57158],[5.868663,49.587],[5.862888,49.58525],[5.851102,49.58379],[5.847116,49.58961],[5.845652,49.5981],[5.869401,49.6106],[5.881819,49.63815],[5.899978,49.63907],[5.899339,49.66239],[5.856561,49.67628],[5.856283,49.68211],[5.875703,49.71118],[5.864811,49.72331],[5.843249,49.71822],[5.82191,49.72128],[5.824894,49.73767],[5.820728,49.74878],[5.786264,49.79079],[5.765172,49.78961],[5.750937,49.79094],[5.741591,49.82126],[5.745814,49.82435],[5.737197,49.83353],[5.740531,49.84142],[5.747012,49.84048],[5.746237,49.84783],[5.753989,49.84878],[5.740663,49.85152],[5.752288,49.85922],[5.749545,49.87554],[5.775668,49.87438],[5.775053,49.88057],[5.734598,49.89341],[5.733033,49.90285],[5.757834,49.91737],[5.760393,49.93252],[5.770728,49.93711],[5.768783,49.94239],[5.768802,49.96104],[5.786724,49.96816],[5.80524,49.96677],[5.806521,49.97321],[5.831293,49.97995],[5.834616,49.98656],[5.818057,49.99936],[5.815606,50.01437],[5.847923,50.02809],[5.861889,50.04581],[5.850872,50.0563],[5.857809,50.07186],[5.880997,50.08069],[5.891965,50.12041],[5.952856,50.13384],[5.961753,50.17631]]],"terms_url":"https://data.public.lu/en/datasets/bd-l-ortho-webservices-wms-et-wmts","terms_text":"Administration du Cadastre et de la Topographie","id":"lu.geoportail.opendata.ortho2010","best":true},{"name":"Luxembourg Geoportail Ortho 2013","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/ortho_2013/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.jpeg","scaleExtent":[0,20],"polygon":[[[5.961753,50.17631],[6.026268,50.18496],[6.033182,50.16395],[6.060695,50.15536],[6.07668,50.15913],[6.078237,50.17255],[6.101762,50.17199],[6.122501,50.16437],[6.120101,50.15594],[6.127695,50.14993],[6.113228,50.13739],[6.123691,50.13719],[6.140929,50.1305],[6.135554,50.11899],[6.138082,50.10263],[6.131085,50.09964],[6.135473,50.09119],[6.121939,50.09059],[6.126335,50.07817],[6.131858,50.07348],[6.121171,50.064],[6.114444,50.06139],[6.115631,50.05817],[6.123611,50.06323],[6.136608,50.04178],[6.130343,50.02975],[6.148207,50.02307],[6.13868,50.01572],[6.135938,50.01485],[6.131384,50.01905],[6.130243,50.01819],[6.139343,50.01116],[6.151702,50.01058],[6.145464,49.99689],[6.139657,49.9994],[6.138524,49.99829],[6.142178,49.99535],[6.150227,49.99518],[6.156247,49.98867],[6.173045,49.98589],[6.17348,49.98344],[6.170353,49.98376],[6.165487,49.97115],[6.171512,49.96298],[6.176298,49.962],[6.179954,49.95386],[6.183393,49.9548],[6.179829,49.96307],[6.183312,49.9686],[6.192774,49.97158],[6.199783,49.95352],[6.207066,49.95672],[6.212689,49.9514],[6.225023,49.95039],[6.22044,49.94369],[6.228241,49.93726],[6.22635,49.92766],[6.219133,49.92354],[6.229862,49.92125],[6.236032,49.91355],[6.231867,49.91064],[6.227694,49.91062],[6.232286,49.9072],[6.23381,49.90028],[6.246919,49.89535],[6.257809,49.88724],[6.263008,49.88101],[6.276455,49.87725],[6.281126,49.87957],[6.291661,49.87548],[6.297699,49.86673],[6.309889,49.87107],[6.315324,49.8673],[6.314651,49.86057],[6.323611,49.85188],[6.321577,49.8409],[6.327406,49.83673],[6.336561,49.83998],[6.339366,49.8507],[6.364651,49.85164],[6.402203,49.82098],[6.426434,49.81629],[6.428071,49.81186],[6.43097,49.81129],[6.441608,49.81547],[6.443442,49.81233],[6.45366,49.81275],[6.464538,49.81975],[6.47057,49.82385],[6.496805,49.81277],[6.50669,49.80993],[6.511554,49.80238],[6.51485,49.80513],[6.519604,49.81446],[6.529808,49.81048],[6.532249,49.80686],[6.530829,49.80116],[6.506225,49.78899],[6.519171,49.78344],[6.511055,49.77422],[6.520563,49.76818],[6.520516,49.76134],[6.503734,49.75086],[6.502627,49.73298],[6.507266,49.72938],[6.518092,49.7242],[6.516417,49.72129],[6.511763,49.72016],[6.504791,49.725],[6.498913,49.72639],[6.495576,49.72443],[6.507122,49.71655],[6.507884,49.71215],[6.504598,49.71227],[6.427139,49.66237],[6.439899,49.66025],[6.442511,49.65591],[6.421781,49.61809],[6.398978,49.60094],[6.379408,49.59526],[6.375507,49.58809],[6.384426,49.5801],[6.381188,49.57509],[6.369093,49.5783],[6.357913,49.57166],[6.384902,49.55817],[6.380095,49.54856],[6.358555,49.53296],[6.359322,49.52481],[6.370763,49.50545],[6.370562,49.45732],[6.333403,49.46493],[6.321894,49.47244],[6.295034,49.47928],[6.287889,49.48379],[6.271912,49.49995],[6.241327,49.50693],[6.196692,49.50331],[6.173373,49.50577],[6.160858,49.50085],[6.167099,49.49006],[6.140179,49.48525],[6.129367,49.48803],[6.127247,49.47081],[6.101403,49.46726],[6.104826,49.45076],[6.081667,49.45417],[6.077222,49.46139],[6.059167,49.46306],[6.052222,49.46028],[6.044213,49.44553],[6.025294,49.44703],[6.021545,49.45127],[6.01574,49.44885],[5.994123,49.45301],[5.976569,49.44885],[5.977725,49.45955],[5.972317,49.46087],[5.968912,49.48202],[5.9616,49.49026],[5.915781,49.49835],[5.890334,49.4948],[5.863321,49.50006],[5.84897,49.50826],[5.84828,49.51397],[5.83641,49.51817],[5.831868,49.52639],[5.84308,49.53081],[5.835622,49.54114],[5.816251,49.53325],[5.805201,49.54272],[5.859432,49.57158],[5.868663,49.587],[5.862888,49.58525],[5.851102,49.58379],[5.847116,49.58961],[5.845652,49.5981],[5.869401,49.6106],[5.881819,49.63815],[5.899978,49.63907],[5.899339,49.66239],[5.856561,49.67628],[5.856283,49.68211],[5.875703,49.71118],[5.864811,49.72331],[5.843249,49.71822],[5.82191,49.72128],[5.824894,49.73767],[5.820728,49.74878],[5.786264,49.79079],[5.765172,49.78961],[5.750937,49.79094],[5.741591,49.82126],[5.745814,49.82435],[5.737197,49.83353],[5.740531,49.84142],[5.747012,49.84048],[5.746237,49.84783],[5.753989,49.84878],[5.740663,49.85152],[5.752288,49.85922],[5.749545,49.87554],[5.775668,49.87438],[5.775053,49.88057],[5.734598,49.89341],[5.733033,49.90285],[5.757834,49.91737],[5.760393,49.93252],[5.770728,49.93711],[5.768783,49.94239],[5.768802,49.96104],[5.786724,49.96816],[5.80524,49.96677],[5.806521,49.97321],[5.831293,49.97995],[5.834616,49.98656],[5.818057,49.99936],[5.815606,50.01437],[5.847923,50.02809],[5.861889,50.04581],[5.850872,50.0563],[5.857809,50.07186],[5.880997,50.08069],[5.891965,50.12041],[5.952856,50.13384],[5.961753,50.17631]]],"terms_url":"https://data.public.lu/en/datasets/bd-l-ortho-webservices-wms-et-wmts","terms_text":"Administration du Cadastre et de la Topographie","id":"lu.geoportail.opendata.ortho2013","best":true},{"name":"Luxembourg Geoportail Topographical Map","type":"tms","template":"https://{switch:wmts3,wmts4}.geoportail.lu/opendata/wmts/topo/GLOBAL_WEBMERCATOR_4_V3/{zoom}/{x}/{y}.png","scaleExtent":[0,20],"polygon":[[[5.961753,50.17631],[6.026268,50.18496],[6.033182,50.16395],[6.060695,50.15536],[6.07668,50.15913],[6.078237,50.17255],[6.101762,50.17199],[6.122501,50.16437],[6.120101,50.15594],[6.127695,50.14993],[6.113228,50.13739],[6.123691,50.13719],[6.140929,50.1305],[6.135554,50.11899],[6.138082,50.10263],[6.131085,50.09964],[6.135473,50.09119],[6.121939,50.09059],[6.126335,50.07817],[6.131858,50.07348],[6.121171,50.064],[6.114444,50.06139],[6.115631,50.05817],[6.123611,50.06323],[6.136608,50.04178],[6.130343,50.02975],[6.148207,50.02307],[6.13868,50.01572],[6.135938,50.01485],[6.131384,50.01905],[6.130243,50.01819],[6.139343,50.01116],[6.151702,50.01058],[6.145464,49.99689],[6.139657,49.9994],[6.138524,49.99829],[6.142178,49.99535],[6.150227,49.99518],[6.156247,49.98867],[6.173045,49.98589],[6.17348,49.98344],[6.170353,49.98376],[6.165487,49.97115],[6.171512,49.96298],[6.176298,49.962],[6.179954,49.95386],[6.183393,49.9548],[6.179829,49.96307],[6.183312,49.9686],[6.192774,49.97158],[6.199783,49.95352],[6.207066,49.95672],[6.212689,49.9514],[6.225023,49.95039],[6.22044,49.94369],[6.228241,49.93726],[6.22635,49.92766],[6.219133,49.92354],[6.229862,49.92125],[6.236032,49.91355],[6.231867,49.91064],[6.227694,49.91062],[6.232286,49.9072],[6.23381,49.90028],[6.246919,49.89535],[6.257809,49.88724],[6.263008,49.88101],[6.276455,49.87725],[6.281126,49.87957],[6.291661,49.87548],[6.297699,49.86673],[6.309889,49.87107],[6.315324,49.8673],[6.314651,49.86057],[6.323611,49.85188],[6.321577,49.8409],[6.327406,49.83673],[6.336561,49.83998],[6.339366,49.8507],[6.364651,49.85164],[6.402203,49.82098],[6.426434,49.81629],[6.428071,49.81186],[6.43097,49.81129],[6.441608,49.81547],[6.443442,49.81233],[6.45366,49.81275],[6.464538,49.81975],[6.47057,49.82385],[6.496805,49.81277],[6.50669,49.80993],[6.511554,49.80238],[6.51485,49.80513],[6.519604,49.81446],[6.529808,49.81048],[6.532249,49.80686],[6.530829,49.80116],[6.506225,49.78899],[6.519171,49.78344],[6.511055,49.77422],[6.520563,49.76818],[6.520516,49.76134],[6.503734,49.75086],[6.502627,49.73298],[6.507266,49.72938],[6.518092,49.7242],[6.516417,49.72129],[6.511763,49.72016],[6.504791,49.725],[6.498913,49.72639],[6.495576,49.72443],[6.507122,49.71655],[6.507884,49.71215],[6.504598,49.71227],[6.427139,49.66237],[6.439899,49.66025],[6.442511,49.65591],[6.421781,49.61809],[6.398978,49.60094],[6.379408,49.59526],[6.375507,49.58809],[6.384426,49.5801],[6.381188,49.57509],[6.369093,49.5783],[6.357913,49.57166],[6.384902,49.55817],[6.380095,49.54856],[6.358555,49.53296],[6.359322,49.52481],[6.370763,49.50545],[6.370562,49.45732],[6.333403,49.46493],[6.321894,49.47244],[6.295034,49.47928],[6.287889,49.48379],[6.271912,49.49995],[6.241327,49.50693],[6.196692,49.50331],[6.173373,49.50577],[6.160858,49.50085],[6.167099,49.49006],[6.140179,49.48525],[6.129367,49.48803],[6.127247,49.47081],[6.101403,49.46726],[6.104826,49.45076],[6.081667,49.45417],[6.077222,49.46139],[6.059167,49.46306],[6.052222,49.46028],[6.044213,49.44553],[6.025294,49.44703],[6.021545,49.45127],[6.01574,49.44885],[5.994123,49.45301],[5.976569,49.44885],[5.977725,49.45955],[5.972317,49.46087],[5.968912,49.48202],[5.9616,49.49026],[5.915781,49.49835],[5.890334,49.4948],[5.863321,49.50006],[5.84897,49.50826],[5.84828,49.51397],[5.83641,49.51817],[5.831868,49.52639],[5.84308,49.53081],[5.835622,49.54114],[5.816251,49.53325],[5.805201,49.54272],[5.859432,49.57158],[5.868663,49.587],[5.862888,49.58525],[5.851102,49.58379],[5.847116,49.58961],[5.845652,49.5981],[5.869401,49.6106],[5.881819,49.63815],[5.899978,49.63907],[5.899339,49.66239],[5.856561,49.67628],[5.856283,49.68211],[5.875703,49.71118],[5.864811,49.72331],[5.843249,49.71822],[5.82191,49.72128],[5.824894,49.73767],[5.820728,49.74878],[5.786264,49.79079],[5.765172,49.78961],[5.750937,49.79094],[5.741591,49.82126],[5.745814,49.82435],[5.737197,49.83353],[5.740531,49.84142],[5.747012,49.84048],[5.746237,49.84783],[5.753989,49.84878],[5.740663,49.85152],[5.752288,49.85922],[5.749545,49.87554],[5.775668,49.87438],[5.775053,49.88057],[5.734598,49.89341],[5.733033,49.90285],[5.757834,49.91737],[5.760393,49.93252],[5.770728,49.93711],[5.768783,49.94239],[5.768802,49.96104],[5.786724,49.96816],[5.80524,49.96677],[5.806521,49.97321],[5.831293,49.97995],[5.834616,49.98656],[5.818057,49.99936],[5.815606,50.01437],[5.847923,50.02809],[5.861889,50.04581],[5.850872,50.0563],[5.857809,50.07186],[5.880997,50.08069],[5.891965,50.12041],[5.952856,50.13384],[5.961753,50.17631]]],"terms_url":"https://data.public.lu/en/datasets/cartes-topographiques-services-wms-et-wmts/","terms_text":"Administration du Cadastre et de la Topographie","id":"lu.geoportail.opendata.topo"},{"name":"Mapbox Satellite","type":"tms","description":"Satellite and aerial imagery.","template":"http://{switch:a,b,c}.tiles.mapbox.com/v4/openstreetmap.map-inh7ifmo/{zoom}/{x}/{y}.png?access_token=pk.eyJ1Ijoib3BlbnN0cmVldG1hcCIsImEiOiJncjlmd0t3In0.DmZsIeOW-3x-C5eX-wAqTw","scaleExtent":[0,19],"terms_url":"http://www.mapbox.com/about/maps/","terms_text":"Terms & Feedback","id":"Mapbox","default":true},{"name":"MD 2014 6 Inch Aerial Imagery","type":"tms","description":"Six Inch resolution aerial imagery for the State of Maryland","template":"http://whoots.mapwarper.net/tms/{z}/{x}/{y}/MD_SixInchImagery/http://geodata.md.gov/imap/services/Imagery/MD_SixInchImagery/MapServer/WmsServer","scaleExtent":[0,20],"polygon":[[[-76.234131,37.920368],[-76.598053,38.158317],[-76.940002,38.270532],[-77.038193,38.413786],[-77.23526,38.33627],[-77.312164,38.410558],[-77.262726,38.566422],[-77.042999,38.713376],[-77.049866,38.793697],[-76.92627,38.892503],[-77.040939,38.984499],[-77.12162,38.925229],[-77.150116,38.955137],[-77.252426,38.975425],[-77.259293,39.024252],[-77.34581,39.054918],[-77.461853,39.070379],[-77.537384,39.139647],[-77.474213,39.224807],[-77.572746,39.304284],[-77.723465,39.328986],[-77.777023,39.463234],[-77.861481,39.516225],[-77.840881,39.608862],[-77.956238,39.59299],[-78.166351,39.695564],[-78.270035,39.621557],[-78.338699,39.640066],[-78.466415,39.523641],[-78.662796,39.540058],[-78.798752,39.606217],[-78.9814,39.446799],[-79.06723,39.476486],[-79.485054,39.199536],[-79.485569,39.72158],[-75.788359,39.721811],[-75.690994,38.460579],[-75.049238,38.458159],[-75.049839,38.402218],[-75.081511,38.323208],[-75.097733,38.309066],[-75.186996,38.097551],[-75.23798,38.022402],[-75.61821,37.989669],[-75.863686,37.909534],[-76.234131,37.920368]]],"terms_url":"http://imap.maryland.gov/Pages/imagery-products.aspx","terms_text":"DoIT, MD iMap, MDP"},{"name":"New & Misaligned TIGER Roads","type":"tms","description":"At zoom level 16+, public domain map data from the US Census. At lower zooms, only changes since 2006 minus changes already incorporated into OpenStreetMap","template":"http://{switch:a,b,c}.tiles.mapbox.com/v4/enf.e0b8291e/{zoom}/{x}/{y}.png?access_token=pk.eyJ1Ijoib3BlbnN0cmVldG1hcCIsImEiOiJhNVlHd29ZIn0.ti6wATGDWOmCnCYen-Ip7Q","scaleExtent":[0,22],"polygon":[[[-124.7617886,48.4130148],[-124.6059492,45.90245],[-124.9934269,40.0557614],[-122.5369737,36.8566086],[-119.9775867,33.0064099],[-117.675935,32.4630223],[-114.8612307,32.4799891],[-111.0089311,31.336015],[-108.1992687,31.3260016],[-108.1871123,31.7755116],[-106.5307225,31.7820947],[-106.4842052,31.7464455],[-106.429317,31.7520583],[-106.2868855,31.5613291],[-106.205248,31.446704],[-105.0205259,30.5360988],[-104.5881916,29.6997856],[-103.2518856,28.8908685],[-102.7173632,29.3920567],[-102.1513983,29.7475702],[-101.2552871,29.4810523],[-100.0062436,28.0082173],[-99.2351068,26.4475962],[-98.0109067,25.9928035],[-97.435024,25.8266009],[-96.9555259,25.9821589],[-96.8061741,27.7978168],[-95.5563349,28.5876066],[-93.7405308,29.4742093],[-90.9028456,28.8564513],[-88.0156706,28.9944338],[-88.0162494,30.0038862],[-86.0277506,30.0047454],[-84.0187909,28.9961781],[-81.9971976,25.9826768],[-81.9966618,25.0134917],[-84.0165592,25.0125783],[-84.0160068,24.0052745],[-80.0199985,24.007096],[-79.8901116,26.8550713],[-80.0245309,32.0161282],[-75.4147385,35.0531894],[-74.0211163,39.5727927],[-72.002019,40.9912464],[-69.8797398,40.9920457],[-69.8489304,43.2619916],[-66.9452845,44.7104937],[-67.7596632,47.0990024],[-69.2505131,47.5122328],[-70.4614886,46.2176574],[-71.412273,45.254878],[-72.0222508,45.0059846],[-75.0798841,44.9802854],[-76.9023061,43.8024568],[-78.7623935,43.6249578],[-79.15798,43.4462589],[-79.0060087,42.8005317],[-82.662475,41.6889458],[-82.1761642,43.588535],[-83.2813977,46.138853],[-87.5064535,48.0142702],[-88.3492194,48.2963271],[-89.4353148,47.9837822],[-93.9981078,49.0067142],[-95.1105379,49.412004],[-96.0131199,49.0060547],[-123.3228926,49.0042878],[-123.2275233,48.1849927],[-124.7617886,48.4130148]],[[-160.5787616,22.5062947],[-160.5782192,21.4984647],[-158.7470604,21.2439843],[-157.5083185,20.995803],[-155.9961942,18.7790194],[-154.6217803,18.7586966],[-154.6890176,19.8805722],[-156.2927622,21.2225888],[-157.5047384,21.9984962],[-159.0093692,22.5070181],[-160.5787616,22.5062947]],[[-167.1571546,68.721974],[-164.8553982,67.0255078],[-168.002195,66.0017503],[-169.0087448,66.001546],[-169.0075381,64.9987675],[-172.5143281,63.8767267],[-173.8197023,59.74014],[-162.5018149,58.0005815],[-160.0159024,58.0012389],[-160.0149725,57.000035],[-160.5054788,56.9999017],[-165.8092575,54.824847],[-178.000097,52.2446469],[-177.9992996,51.2554252],[-171.4689067,51.8215329],[-162.40251,53.956664],[-159.0075717,55.002502],[-158.0190709,55.0027849],[-151.9963213,55.9991902],[-151.500341,57.9987853],[-151.5012894,58.9919816],[-138.5159989,58.9953194],[-138.5150471,57.9986434],[-133.9948193,54.0031685],[-130.0044418,54.0043387],[-130.0070826,57.0000507],[-131.975877,56.9995156],[-135.1229873,59.756601],[-138.0071813,59.991805],[-139.1715881,60.4127229],[-140.9874011,61.0118551],[-140.9683975,69.9535069],[-156.176891,71.5633329],[-160.413634,70.7397728],[-163.0218273,69.9707435],[-164.9717003,68.994689],[-167.1571546,68.721974]]],"overlay":true},{"name":"NJ 2015 Aerial Imagery (Infrared)","type":"tms","description":"Digital orthophotography of New Jersey, Near Infrared, 1 foot resolution","template":"http://whoots.mapwarper.net/tms/{z}/{x}/{y}/Infrared2015/http://geodata.state.nj.us/imagerywms/Infrared2015","scaleExtent":[0,20],"polygon":[[[-74.86599,40.085427],[-74.840927,40.107225],[-74.822903,40.130329],[-74.788055,40.124685],[-74.726086,40.149488],[-74.729176,40.16392],[-74.763336,40.191725],[-74.775524,40.214276],[-74.844017,40.247957],[-74.868393,40.291573],[-74.944611,40.33817],[-74.967098,40.395195],[-75.002632,40.406046],[-75.026836,40.402516],[-75.06134,40.416502],[-75.074215,40.455046],[-75.069065,40.536503],[-75.102367,40.567024],[-75.135927,40.573609],[-75.16777,40.559069],[-75.197639,40.573674],[-75.203733,40.618318],[-75.205064,40.691312],[-75.198326,40.753889],[-75.172405,40.780671],[-75.1367,40.777292],[-75.090179,40.822383],[-75.100994,40.839269],[-75.096874,40.850956],[-75.068464,40.850372],[-75.057049,40.867574],[-75.13773,40.973094],[-75.135155,40.994411],[-75.039024,41.03819],[-74.981518,41.112598],[-74.905472,41.170384],[-74.84024,41.278645],[-74.798012,41.322685],[-74.757156,41.347691],[-74.695702,41.360576],[-74.041054,41.059088],[-74.041051,41.059087],[-74.04105,41.059087],[-74.04105,41.059086],[-74.041049,41.059086],[-74.041049,41.059086],[-73.890266,40.998039],[-73.933406,40.882078],[-73.933407,40.882077],[-73.933408,40.882076],[-73.933408,40.882075],[-73.933408,40.882075],[-74.011459,40.75558],[-74.024543,40.709436],[-74.066048,40.651732],[-74.152222,40.638967],[-74.183121,40.644568],[-74.200459,40.631281],[-74.199257,40.598444],[-74.21505,40.558026],[-74.246807,40.548113],[-74.24715,40.519541],[-74.267578,40.489651],[-74.26054,40.469282],[-74.199257,40.445641],[-74.181061,40.460401],[-74.136429,40.459095],[-73.997555,40.413496],[-74.026566,40.47777],[-74.003906,40.484037],[-73.977814,40.452042],[-73.964767,40.33189],[-74.088364,39.756824],[-74.356842,39.383406],[-74.609528,39.215231],[-74.776382,38.998909],[-74.863586,38.931639],[-74.931221,38.920688],[-74.980316,38.930304],[-74.960747,39.00798],[-74.905472,39.100226],[-74.899979,39.164141],[-75.101166,39.201398],[-75.135498,39.171062],[-75.425949,39.378099],[-75.475044,39.43195],[-75.543365,39.457403],[-75.552292,39.482845],[-75.538902,39.541911],[-75.519676,39.56997],[-75.571175,39.608069],[-75.577698,39.625524],[-75.539932,39.656456],[-75.472984,39.747454],[-75.466253,39.750761],[-75.466252,39.750762],[-75.466252,39.750763],[-75.466252,39.750763],[-75.466252,39.750763],[-75.466251,39.750764],[-75.466251,39.750765],[-75.466251,39.750765],[-75.466251,39.750765],[-75.466251,39.750765],[-75.46625,39.750767],[-75.466249,39.750768],[-75.466249,39.750769],[-75.466249,39.750769],[-75.465088,39.764478],[-75.415041,39.801786],[-75.324669,39.858891],[-75.246048,39.864689],[-75.143738,39.900255],[-75.142365,39.957912],[-75.07061,39.987117],[-75.056534,40.008683],[-74.935341,40.072555],[-74.86599,40.085427]]],"terms_url":"https://njgin.state.nj.us/NJ_NJGINExplorer/ShowMetadata.jsp?docId={E30775F2-6370-4525-8E68-C371ED29BBB3}","terms_text":"NJ Office of Information Technology (NJOIT), Office of Geographic Information Systems (OGIS)"},{"name":"NJ 2015 Aerial Imagery (Natural Color)","type":"tms","description":"Digital orthophotography of New Jersey, Natural Color, 1 foot resolution","template":"http://whoots.mapwarper.net/tms/{z}/{x}/{y}/Natural2015/http://geodata.state.nj.us/imagerywms/Natural2015","scaleExtent":[0,20],"polygon":[[[-74.86599,40.085427],[-74.840927,40.107225],[-74.822903,40.130329],[-74.788055,40.124685],[-74.726086,40.149488],[-74.729176,40.16392],[-74.763336,40.191725],[-74.775524,40.214276],[-74.844017,40.247957],[-74.868393,40.291573],[-74.944611,40.33817],[-74.967098,40.395195],[-75.002632,40.406046],[-75.026836,40.402516],[-75.06134,40.416502],[-75.074215,40.455046],[-75.069065,40.536503],[-75.102367,40.567024],[-75.135927,40.573609],[-75.16777,40.559069],[-75.197639,40.573674],[-75.203733,40.618318],[-75.205064,40.691312],[-75.198326,40.753889],[-75.172405,40.780671],[-75.1367,40.777292],[-75.090179,40.822383],[-75.100994,40.839269],[-75.096874,40.850956],[-75.068464,40.850372],[-75.057049,40.867574],[-75.13773,40.973094],[-75.135155,40.994411],[-75.039024,41.03819],[-74.981518,41.112598],[-74.905472,41.170384],[-74.84024,41.278645],[-74.798012,41.322685],[-74.757156,41.347691],[-74.695702,41.360576],[-74.041054,41.059088],[-74.041051,41.059087],[-74.04105,41.059087],[-74.04105,41.059086],[-74.041049,41.059086],[-74.041049,41.059086],[-73.890266,40.998039],[-73.933406,40.882078],[-73.933407,40.882077],[-73.933408,40.882076],[-73.933408,40.882075],[-73.933408,40.882075],[-74.011459,40.75558],[-74.024543,40.709436],[-74.066048,40.651732],[-74.152222,40.638967],[-74.183121,40.644568],[-74.200459,40.631281],[-74.199257,40.598444],[-74.21505,40.558026],[-74.246807,40.548113],[-74.24715,40.519541],[-74.267578,40.489651],[-74.26054,40.469282],[-74.199257,40.445641],[-74.181061,40.460401],[-74.136429,40.459095],[-73.997555,40.413496],[-74.026566,40.47777],[-74.003906,40.484037],[-73.977814,40.452042],[-73.964767,40.33189],[-74.088364,39.756824],[-74.356842,39.383406],[-74.609528,39.215231],[-74.776382,38.998909],[-74.863586,38.931639],[-74.931221,38.920688],[-74.980316,38.930304],[-74.960747,39.00798],[-74.905472,39.100226],[-74.899979,39.164141],[-75.101166,39.201398],[-75.135498,39.171062],[-75.425949,39.378099],[-75.475044,39.43195],[-75.543365,39.457403],[-75.552292,39.482845],[-75.538902,39.541911],[-75.519676,39.56997],[-75.571175,39.608069],[-75.577698,39.625524],[-75.539932,39.656456],[-75.472984,39.747454],[-75.466253,39.750761],[-75.466252,39.750762],[-75.466252,39.750763],[-75.466252,39.750763],[-75.466252,39.750763],[-75.466251,39.750764],[-75.466251,39.750765],[-75.466251,39.750765],[-75.466251,39.750765],[-75.466251,39.750765],[-75.46625,39.750767],[-75.466249,39.750768],[-75.466249,39.750769],[-75.466249,39.750769],[-75.465088,39.764478],[-75.415041,39.801786],[-75.324669,39.858891],[-75.246048,39.864689],[-75.143738,39.900255],[-75.142365,39.957912],[-75.07061,39.987117],[-75.056534,40.008683],[-74.935341,40.072555],[-74.86599,40.085427]]],"terms_url":"https://njgin.state.nj.us/NJ_NJGINExplorer/ShowMetadata.jsp?docId={CDC67AB8-ADA1-4B4B-9087-67A82CB9151C}","terms_text":"NJ Office of Information Technology (NJOIT), Office of Geographic Information Systems (OGIS)"},{"name":"NLS - Bartholomew Half Inch, 1897-1907","type":"tms","template":"http://geo.nls.uk/mapdata2/bartholomew/great_britain/{zoom}/{x}/{-y}.png","scaleExtent":[0,15],"polygon":[[[-9,49.8],[-9,61.1],[1.9,61.1],[1.9,49.8],[-9,49.8]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps"},{"name":"NLS - OS 1-inch 7th Series 1955-61","type":"tms","template":"http://geo.nls.uk/mapdata2/os/seventh/{zoom}/{x}/{-y}.png","scaleExtent":[5,16],"polygon":[[[-6.4585407,49.9044128],[-6.3872009,49.9841116],[-6.2296827,49.9896159],[-6.2171269,49.8680087],[-6.4551164,49.8591793],[-6.4585407,49.9044128]],[[-1.4495137,60.8634056],[-0.7167114,60.8545122],[-0.7349744,60.4359756],[-0.6938826,60.4168218],[-0.7258429,60.3942735],[-0.7395401,60.0484714],[-0.9267357,60.0461918],[-0.9381501,59.8266157],[-1.4586452,59.831205],[-1.4455187,60.0535999],[-1.463211,60.0535999],[-1.4643524,60.0630002],[-1.5716475,60.0638546],[-1.5693646,60.1790005],[-1.643558,60.1807033],[-1.643558,60.1892162],[-1.8216221,60.1894999],[-1.8204807,60.3615507],[-1.8415973,60.3697345],[-1.8216221,60.3832755],[-1.8179852,60.5934321],[-1.453168,60.5934321],[-1.4495137,60.8634056]],[[-4.9089213,54.4242078],[-4.282598,54.4429861],[-4.2535417,54.029769],[-4.8766366,54.0221831],[-4.9089213,54.4242078]],[[-5.8667408,59.1444603],[-5.7759966,59.1470945],[-5.7720016,59.1014052],[-5.8621751,59.0990605],[-5.8667408,59.1444603]],[[-1.7065887,59.5703599],[-1.5579165,59.5693481],[-1.5564897,59.4965695],[-1.7054472,59.4975834],[-1.7065887,59.5703599]],[[-7.6865827,58.2940975],[-7.5330594,58.3006957],[-7.5256401,58.2646905],[-7.6797341,58.2577853],[-7.6865827,58.2940975]],[[-4.5338281,59.0359871],[-4.481322,59.0371616],[-4.4796099,59.0186583],[-4.5332574,59.0180707],[-4.5338281,59.0359871]],[[-8.6710698,57.8769896],[-8.4673234,57.8897332],[-8.4467775,57.7907],[-8.6510947,57.7779213],[-8.6710698,57.8769896]],[[-5.2395519,50.3530581],[-5.7920073,50.3384899],[-5.760047,49.9317027],[-4.6551363,49.9581461],[-4.677965,50.2860073],[-4.244219,50.2801723],[-4.2487848,50.2042525],[-3.3812929,50.2042525],[-3.4223846,50.5188201],[-3.1164796,50.5246258],[-3.1210453,50.6579592],[-2.6736357,50.6619495],[-2.5953453,50.6394325],[-2.5905026,50.5728419],[-2.4791203,50.5733545],[-2.4758919,50.5066704],[-2.3967943,50.5056438],[-2.401637,50.5723293],[-1.0400296,50.5718167],[-1.0335726,50.7059289],[-0.549302,50.7038843],[-0.5460736,50.7886618],[-0.0924734,50.7856002],[-0.0876307,50.7181949],[0.4789659,50.7120623],[0.487037,50.8182467],[0.9761503,50.8049868],[0.9922927,51.0126311],[1.4491213,51.0004424],[1.4781775,51.4090372],[1.0229632,51.4271576],[1.035877,51.7640881],[1.6105448,51.7500992],[1.646058,52.1560003],[1.7267698,52.1540195],[1.749369,52.4481811],[1.7870672,52.4811624],[1.759102,52.522505],[1.7933451,52.9602749],[0.3798147,52.9958468],[0.3895238,53.2511239],[0.3478614,53.2511239],[0.3238912,53.282186],[0.3461492,53.6538501],[0.128487,53.6575466],[0.116582,53.6674703],[0.1350586,54.0655731],[-0.0609831,54.065908],[-0.0414249,54.4709448],[-0.5662701,54.4771794],[-0.5592078,54.6565127],[-1.1665638,54.6623485],[-1.1637389,54.842611],[-1.3316194,54.843909],[-1.3257065,55.2470842],[-1.529453,55.2487108],[-1.524178,55.6540122],[-1.7638798,55.6540122],[-1.7733693,55.9719116],[-2.1607858,55.9682981],[-2.1543289,56.0621387],[-2.4578051,56.0585337],[-2.4190635,56.641717],[-2.0962164,56.641717],[-2.0833025,57.0021322],[-1.9283359,57.0126802],[-1.9180966,57.3590895],[-1.7502161,57.3625721],[-1.7695869,57.7608634],[-3.6937554,57.7574187],[-3.7066693,57.9806386],[-3.5969013,57.9772149],[-3.6033582,58.1207277],[-3.0222335,58.1309566],[-3.0286905,58.5410788],[-2.8478961,58.530968],[-2.86081,58.8430508],[-2.679624,58.8414991],[-2.6841897,58.885175],[-2.6339665,58.9052239],[-2.679624,58.9335083],[-2.6887555,59.0229231],[-2.3668703,59.0229231],[-2.3702946,59.2652861],[-2.3429001,59.2821989],[-2.3714361,59.2996861],[-2.3737189,59.3707083],[-2.3429001,59.385825],[-2.3725775,59.400354],[-2.3714361,59.4259098],[-3.0734196,59.4230067],[-3.0711368,59.3433649],[-3.103097,59.3311405],[-3.0745611,59.3136695],[-3.0722782,59.232603],[-3.3850319,59.1484167],[-3.3747589,58.9352753],[-3.5653789,58.9323303],[-3.554829,58.69759],[-5.2808579,58.6667732],[-5.2534159,58.3514125],[-5.5068508,58.3437887],[-5.4761804,58.0323557],[-5.8974958,58.0212436],[-5.8522972,57.6171758],[-6.1396311,57.6137174],[-6.1541592,57.7423183],[-6.2913692,57.7380102],[-6.3365678,58.1398784],[-6.1121891,58.1466944],[-6.1473778,58.5106285],[-6.2934817,58.5416182],[-6.8413713,58.2977321],[-7.0057382,58.2929331],[-7.1016189,58.2064403],[-7.2573132,58.1793148],[-7.2531092,58.1004928],[-7.4070698,58.0905566],[-7.391347,57.7911354],[-7.790991,57.7733151],[-7.7624215,57.5444165],[-7.698501,57.1453194],[-7.7943817,57.1304547],[-7.716764,56.7368628],[-7.0122067,56.7654359],[-6.979922,56.5453858],[-7.0638622,56.5453858],[-7.0444914,56.3562587],[-6.500676,56.3812917],[-6.4491433,55.9793649],[-6.563287,55.9691456],[-6.5393742,55.7030135],[-6.5595521,55.6907321],[-6.5345315,55.6761713],[-6.5216176,55.5704434],[-5.8912587,55.5923416],[-5.8560127,55.2320733],[-5.2293639,55.2515958],[-5.1837064,54.6254139],[-3.6655956,54.6518373],[-3.6496155,54.4320023],[-3.5400375,54.4306744],[-3.530906,54.0290181],[-3.0697656,54.030359],[-3.0675737,53.8221388],[-3.0804876,53.7739911],[-3.0619239,53.7477488],[-3.0611168,53.6737049],[-3.2144691,53.6708361],[-3.2057699,53.4226163],[-3.2799632,53.355224],[-3.2896655,53.3608441],[-3.3327547,53.364931],[-3.3761293,53.3540318],[-4.0888976,53.3433102],[-4.0945474,53.4612036],[-4.697412,53.4448624],[-4.6882805,53.3318598],[-4.7202407,53.2895771],[-4.6837148,53.2486184],[-4.6768661,53.1542644],[-4.8480816,53.1446807],[-4.8178336,52.7440299],[-4.2545751,52.7558939],[-4.228876,52.254876],[-4.2607571,52.2536408],[-4.2724603,52.2432637],[-4.8136263,52.230095],[-4.8079191,52.1138892],[-5.3889104,52.0991668],[-5.3717888,51.9129667],[-5.4208706,51.9101502],[-5.414022,51.8453218],[-5.3683645,51.8474373],[-5.3466772,51.5595332],[-4.773676,51.5758518],[-4.7656859,51.4885146],[-4.1915432,51.4970427],[-4.1869775,51.4344663],[-3.6151177,51.4444274],[-3.6105519,51.3746543],[-3.1494115,51.3789292],[-3.1494115,51.2919281],[-4.3038735,51.2745907],[-4.2861169,51.0508721],[-4.8543277,51.0366633],[-4.8372201,50.7212787],[-5.2618345,50.7082694],[-5.2395519,50.3530581]],[[-2.1502671,60.171318],[-2.0030218,60.1696146],[-2.0013096,60.0997023],[-2.148555,60.1011247],[-2.1502671,60.171318]],[[-6.2086011,59.1163488],[-6.1229934,59.1166418],[-6.121852,59.0714985],[-6.2097426,59.0714985],[-6.2086011,59.1163488]],[[-4.4159559,59.0889036],[-4.4212022,59.0770848],[-4.3971904,59.0779143],[-4.3913388,59.0897328],[-4.4159559,59.0889036]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps"},{"name":"NLS - OS 1:25k 1st Series 1937-61","type":"tms","template":"http://geo.nls.uk/mapdata2/os/25000/{zoom}/{x}/{-y}.png","scaleExtent":[5,16],"polygon":[[[-4.7157244,54.6796556],[-4.6850662,54.6800268],[-4.6835779,54.6623245],[-4.7148782,54.6615818],[-4.7157244,54.6796556]],[[-3.7085748,58.3371151],[-3.5405937,58.3380684],[-3.5315137,58.1608002],[-3.3608086,58.1622372],[-3.3653486,58.252173],[-3.1610473,58.2536063],[-3.1610473,58.3261509],[-3.0275704,58.3271045],[-3.0366505,58.6139001],[-3.0021463,58.614373],[-3.0030543,58.7036341],[-3.4180129,58.7003322],[-3.4171049,58.6290293],[-3.7240109,58.6266658],[-3.7231029,58.606806],[-4.2361262,58.5992374],[-4.2334022,58.5092347],[-3.88836,58.5144516],[-3.8829119,58.4261327],[-3.7158389,58.4270836],[-3.7085748,58.3371151]],[[-6.46676,49.9943621],[-6.1889102,50.004868],[-6.1789222,49.8967815],[-6.3169391,49.8915171],[-6.312399,49.8200979],[-6.4504159,49.8159968],[-6.46676,49.9943621]],[[-5.6453263,50.2029809],[-5.7801329,50.2014076],[-5.7637888,50.0197267],[-5.3479221,50.0290604],[-5.3388421,49.9414854],[-5.024672,49.9473287],[-5.0355681,50.0383923],[-5.0010639,50.0453901],[-4.9974319,50.1304478],[-4.855783,50.13394],[-4.861231,50.206057],[-4.6546085,50.2140172],[-4.6558926,50.3018616],[-4.5184924,50.3026818],[-4.51464,50.325642],[-4.2488284,50.3264618],[-4.2488284,50.3100631],[-4.10886,50.3141633],[-4.1062917,50.2411267],[-3.9648088,50.2432047],[-3.9640778,50.2254158],[-3.8522287,50.2273626],[-3.8503757,50.1552563],[-3.6921809,50.1572487],[-3.5414602,50.1602198],[-3.5465781,50.3226814],[-3.4068012,50.3241013],[-3.4165761,50.5892711],[-3.2746691,50.5962721],[-3.2749172,50.6106323],[-2.9971742,50.613972],[-2.9896008,50.688537],[-2.7120266,50.690565],[-2.710908,50.6195964],[-2.5695473,50.6157538],[-2.5651019,50.5134083],[-2.4014463,50.513379],[-2.3940583,50.6160348],[-2.2894123,50.6147436],[-2.2876184,50.6008549],[-2.1477855,50.6048506],[-2.1451013,50.5325437],[-1.9335117,50.5347477],[-1.9362139,50.6170445],[-1.8573025,50.6228094],[-1.8554865,50.709139],[-1.6066929,50.709139],[-1.6085089,50.6239615],[-1.4450678,50.6228094],[-1.4432518,50.5317039],[-1.1545059,50.5293951],[-1.1472419,50.6170485],[-1.011041,50.6205051],[-1.011041,50.7056889],[-0.704135,50.7045388],[-0.700503,50.7769401],[-0.5860943,50.7723465],[-0.5879103,50.7907181],[-0.0149586,50.7798108],[-0.0185906,50.7625836],[0.0967261,50.7620093],[0.0921861,50.6913106],[0.3046595,50.6890096],[0.3101075,50.7757917],[0.5511831,50.7726336],[0.5529991,50.8432096],[0.695556,50.8403428],[0.696464,50.8592608],[0.9852099,50.8523824],[0.9906579,50.9417226],[1.0160821,50.9411504],[1.0215301,51.0303204],[1.2812198,51.0240383],[1.2848518,51.0948044],[1.4277848,51.0948044],[1.4386809,51.2882859],[1.4713691,51.2871502],[1.4804492,51.3994534],[1.1590151,51.4073836],[1.1590151,51.3869889],[1.0191822,51.3903886],[1.0228142,51.4798247],[0.8793493,51.4843484],[0.8829813,51.5566675],[1.0264462,51.5544092],[1.0373423,51.7493319],[1.2607117,51.7482076],[1.2661598,51.8279642],[1.3351682,51.8335756],[1.3478803,51.9199021],[1.4840812,51.9199021],[1.4986093,52.0038271],[1.6438902,52.0027092],[1.6656823,52.270221],[1.7310588,52.270221],[1.7528509,52.4465637],[1.8254914,52.4476705],[1.8345714,52.624408],[1.7690346,52.6291402],[1.7741711,52.717904],[1.6996925,52.721793],[1.706113,52.8103687],[1.559724,52.8165777],[1.5648605,52.9034116],[1.4184715,52.9103818],[1.4223238,52.9281894],[1.3439928,52.9289635],[1.3491293,53.0001194],[0.4515789,53.022589],[0.4497629,52.9351139],[0.3789384,52.9351139],[0.3716744,52.846365],[0.2227614,52.8496552],[0.2336575,52.9329248],[0.3062979,52.9351139],[0.308114,53.022589],[0.3807544,53.0236813],[0.3993708,53.2933729],[0.3248922,53.2987454],[0.3274604,53.3853782],[0.2504136,53.38691],[0.2581183,53.4748924],[0.1862079,53.4779494],[0.1913443,53.6548777],[0.1502527,53.6594436],[0.1528209,53.7666003],[0.0012954,53.7734308],[0.0025796,53.8424326],[-0.0282392,53.841675],[-0.0226575,53.9311501],[-0.1406983,53.9322193],[-0.1416063,54.0219323],[-0.1706625,54.0235326],[-0.1679384,54.0949482],[-0.0126694,54.0912206],[-0.0099454,54.1811226],[-0.1615824,54.1837795],[-0.1606744,54.2029038],[-0.2405789,54.2034349],[-0.2378549,54.2936234],[-0.3894919,54.2941533],[-0.3857497,54.3837321],[-0.461638,54.3856364],[-0.4571122,54.4939066],[-0.6105651,54.4965434],[-0.6096571,54.5676704],[-0.7667421,54.569776],[-0.7640181,54.5887213],[-0.9192871,54.5908258],[-0.9148116,54.6608348],[-1.1485204,54.6634343],[-1.1472363,54.7528316],[-1.2268514,54.7532021],[-1.2265398,54.8429879],[-1.2991803,54.8435107],[-1.2991803,54.9333391],[-1.3454886,54.9354258],[-1.3436726,55.0234878],[-1.3772688,55.0255698],[-1.3754528,55.1310877],[-1.4997441,55.1315727],[-1.4969272,55.2928323],[-1.5296721,55.2942946],[-1.5258198,55.6523803],[-1.7659492,55.6545537],[-1.7620968,55.7435626],[-1.9688392,55.7435626],[-1.9698023,55.8334505],[-2.0019051,55.8336308],[-2.0015841,55.9235526],[-2.1604851,55.9240613],[-2.1613931,55.9413549],[-2.3202942,55.9408463],[-2.3212022,56.0145126],[-2.5627317,56.0124824],[-2.5645477,56.1022207],[-2.9658863,56.0991822],[-2.9667943,56.1710304],[-2.4828272,56.1755797],[-2.4882752,56.2856078],[-2.5645477,56.2835918],[-2.5681798,56.3742075],[-2.7261728,56.3732019],[-2.7316208,56.4425301],[-2.6190281,56.4425301],[-2.6153961,56.5317671],[-2.453771,56.5347715],[-2.4534686,56.6420248],[-2.4062523,56.6440218],[-2.3953562,56.7297964],[-2.2936596,56.7337811],[-2.2972916,56.807423],[-2.1629067,56.8113995],[-2.1592747,56.9958425],[-1.9922016,57.0017771],[-2.0067297,57.2737477],[-1.9195612,57.2757112],[-1.9304572,57.3482876],[-1.8106005,57.3443682],[-1.7997044,57.4402728],[-1.6616875,57.4285429],[-1.6689516,57.5398256],[-1.7452241,57.5398256],[-1.7524881,57.6313302],[-1.8287606,57.6332746],[-1.8287606,57.7187255],[-3.1768526,57.7171219],[-3.1794208,57.734264],[-3.5134082,57.7292105],[-3.5129542,57.7112683],[-3.7635638,57.7076303],[-3.7598539,57.635713],[-3.8420372,57.6343382],[-3.8458895,57.6178365],[-3.9794374,57.6157733],[-3.9794374,57.686544],[-3.8150708,57.689976],[-3.817639,57.7968899],[-3.6853753,57.7989429],[-3.6892276,57.8891567],[-3.9383458,57.8877915],[-3.9421981,57.9750592],[-3.6943641,57.9784638],[-3.6969323,58.0695865],[-4.0372226,58.0641528],[-4.0346543,57.9730163],[-4.2003051,57.9702923],[-4.1832772,57.7012869],[-4.518752,57.6951111],[-4.5122925,57.6050682],[-4.6789116,57.6016628],[-4.666022,57.4218334],[-3.6677696,57.4394729],[-3.671282,57.5295384],[-3.3384979,57.5331943],[-3.3330498,57.4438859],[-2.8336466,57.4485275],[-2.8236396,56.9992706],[-2.3305398,57.0006693],[-2.3298977,56.9113932],[-2.6579889,56.9092901],[-2.6559637,56.8198406],[-2.8216747,56.8188467],[-2.8184967,56.7295397],[-3.1449248,56.7265508],[-3.1435628,56.6362749],[-3.4679089,56.6350265],[-3.474265,56.7238108],[-3.8011471,56.7188284],[-3.785711,56.4493026],[-3.946428,56.4457896],[-3.9428873,56.2659777],[-4.423146,56.2588459],[-4.4141572,56.0815506],[-4.8944159,56.0708008],[-4.8791072,55.8896994],[-5.1994158,55.8821374],[-5.1852906,55.7023791],[-5.0273445,55.7067203],[-5.0222081,55.6879046],[-4.897649,55.6907999],[-4.8880181,55.6002822],[-4.7339244,55.6046348],[-4.7275038,55.5342082],[-4.773732,55.5334815],[-4.7685955,55.4447227],[-4.8494947,55.4418092],[-4.8405059,55.3506535],[-4.8700405,55.3513836],[-4.8649041,55.2629462],[-4.9920314,55.2592875],[-4.9907473,55.1691779],[-5.0600894,55.1655105],[-5.0575212,55.0751884],[-5.2141831,55.0722477],[-5.1991766,54.8020337],[-5.0466316,54.8062205],[-5.0502636,54.7244996],[-4.9703591,54.7203043],[-4.9776232,54.6215905],[-4.796022,54.6342056],[-4.796022,54.7307917],[-4.8977186,54.7265971],[-4.9086147,54.8145928],[-4.8069181,54.8166856],[-4.8105501,54.7915648],[-4.6943253,54.7978465],[-4.6761652,54.7244996],[-4.5744686,54.7244996],[-4.5599405,54.6426135],[-4.3093309,54.6384098],[-4.3333262,54.8229889],[-4.2626999,54.8274274],[-4.2549952,54.7348587],[-3.8338058,54.7400481],[-3.836374,54.8141105],[-3.7118149,54.8133706],[-3.7143831,54.8318654],[-3.5346072,54.8355633],[-3.5271039,54.9066228],[-3.4808758,54.9084684],[-3.4776655,54.7457328],[-3.5874573,54.744621],[-3.5836049,54.6546166],[-3.7107322,54.6531308],[-3.6991752,54.4550407],[-3.5746161,54.4572801],[-3.5759002,54.3863042],[-3.539945,54.3855564],[-3.5386609,54.297224],[-3.46033,54.2957252],[-3.4590458,54.2079507],[-3.3807149,54.2102037],[-3.381999,54.1169788],[-3.302878,54.1160656],[-3.300154,54.0276224],[-3.1013007,54.0292224],[-3.093596,53.6062158],[-3.2065981,53.6016441],[-3.2091663,53.4917753],[-3.2451215,53.4887193],[-3.2348486,53.4045934],[-3.5276266,53.3999999],[-3.5343966,53.328481],[-3.6488053,53.3252272],[-3.6527308,53.3057716],[-3.7271873,53.3046865],[-3.7315003,53.3945257],[-3.9108315,53.3912769],[-3.9071995,53.3023804],[-3.9521457,53.3015665],[-3.9566724,53.3912183],[-4.1081979,53.3889209],[-4.1081979,53.4072967],[-4.2622916,53.4065312],[-4.2635757,53.4753707],[-4.638537,53.4677274],[-4.6346847,53.3812621],[-4.7091633,53.3774321],[-4.7001745,53.1954965],[-4.5499332,53.1962658],[-4.5435126,53.1092488],[-4.3919871,53.1100196],[-4.3855666,53.0236002],[-4.6115707,53.0205105],[-4.603866,52.9284932],[-4.7566756,52.9261709],[-4.7476868,52.8370555],[-4.8208813,52.8331768],[-4.8208813,52.7446476],[-4.3701572,52.7539749],[-4.3765778,52.8401583],[-4.2314728,52.8455875],[-4.2237682,52.7586379],[-4.1056297,52.7570836],[-4.1015192,52.6714874],[-4.1487355,52.6703862],[-4.1305754,52.4008596],[-4.1995838,52.3986435],[-4.2050319,52.3110195],[-4.3466808,52.303247],[-4.3484968,52.2365693],[-4.4901457,52.2332328],[-4.4883297,52.2098702],[-4.6572188,52.2098702],[-4.6590348,52.1385939],[-4.7788916,52.13525],[-4.7807076,52.1162967],[-4.9259885,52.1140663],[-4.9187245,52.0392855],[-5.2365265,52.0314653],[-5.2347105,51.9442339],[-5.3473032,51.9408755],[-5.3473032,51.9195995],[-5.4925842,51.9162392],[-5.4853201,51.8265386],[-5.1983903,51.8321501],[-5.1893102,51.7625177],[-5.335825,51.7589528],[-5.3281204,51.6686495],[-5.1836575,51.6730296],[-5.1836575,51.6539134],[-5.0674452,51.6578966],[-5.0603825,51.5677905],[-4.5974594,51.5809588],[-4.60388,51.6726314],[-4.345773,51.6726314],[-4.3355001,51.4962964],[-3.9528341,51.5106841],[-3.9425611,51.5905333],[-3.8809237,51.5953198],[-3.8706508,51.5074872],[-3.7679216,51.4978952],[-3.7550805,51.4242895],[-3.5855774,51.41468],[-3.5778727,51.3329177],[-3.0796364,51.3329177],[-3.0770682,51.2494018],[-3.7216935,51.2381477],[-3.7216935,51.2558315],[-3.8706508,51.2558315],[-3.8680825,51.2365398],[-4.2944084,51.2252825],[-4.289272,51.0496352],[-4.5692089,51.0431767],[-4.5624122,50.9497388],[-4.5905604,50.9520269],[-4.5896524,50.8627065],[-4.6296046,50.8592677],[-4.6226411,50.7691513],[-4.6952816,50.7680028],[-4.6934655,50.6967379],[-4.8342064,50.6938621],[-4.8296664,50.6046231],[-4.9676833,50.6000126],[-4.9685913,50.5821427],[-5.1084242,50.5786832],[-5.1029762,50.4892254],[-5.1311244,50.48807],[-5.1274923,50.4163798],[-5.2664172,50.4117509],[-5.2609692,50.3034214],[-5.5124868,50.2976214],[-5.5061308,50.2256428],[-5.6468717,50.2209953],[-5.6453263,50.2029809]],[[-5.1336607,55.2630226],[-5.1021999,55.2639372],[-5.0999527,55.2458239],[-5.1322161,55.2446343],[-5.1336607,55.2630226]],[[-5.6431878,55.5095745],[-5.4861028,55.5126594],[-5.4715747,55.3348829],[-5.6277517,55.3302345],[-5.6431878,55.5095745]],[[-4.7213517,51.2180246],[-4.5804201,51.2212417],[-4.5746416,51.1306736],[-4.7174993,51.1280545],[-4.7213517,51.2180246]],[[-5.1608796,55.4153626],[-5.0045387,55.4190069],[-5.0184798,55.6153521],[-5.1755648,55.6138137],[-5.1608796,55.4153626]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps"},{"name":"NLS - OS 25-inch (Scotland), 1892-1905","type":"tms","template":"http://geo.nls.uk/mapdata2/os/25_inch/scotland_1/{zoom}/{x}/{y}.png","scaleExtent":[0,18],"polygon":[[[-9.25,54.43],[-9.25,61.12],[0.22,61.12],[0.22,54.43],[-9.25,54.43]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps"},{"name":"NLS - OS 6-inch County Series, 1888-1913","type":"tms","template":"http://geo.nls.uk/mapdata3/os/6_inch_gb_1900/{zoom}/{x}/{y}.png","scaleExtent":[0,17],"polygon":[[[-9,49.8],[-9,61.1],[1.9,61.1],[1.9,49.8],[-9,49.8]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps"},{"name":"NLS - OS 6-inch Scotland 1842-82","type":"tms","template":"http://geo.nls.uk/maps/os/six_inch/{zoom}/{x}/{-y}.png","scaleExtent":[5,16],"polygon":[[[-5.2112173,54.8018593],[-5.0642752,54.8026508],[-5.0560354,54.6305176],[-4.3158316,54.6297227],[-4.3117117,54.7448258],[-3.8530325,54.7464112],[-3.8530325,54.8034424],[-3.5522818,54.8034424],[-3.5522818,54.8374644],[-3.468511,54.8406277],[-3.4657644,54.8983158],[-3.3847403,54.8991055],[-3.3888601,54.9559214],[-3.0920786,54.9539468],[-3.0392359,54.9923274],[-3.0212713,55.0493881],[-2.9591232,55.0463283],[-2.9202807,55.0666294],[-2.7857081,55.068652],[-2.7852225,55.0914426],[-2.7337562,55.0922761],[-2.737616,55.151204],[-2.7648395,55.1510672],[-2.7013114,55.1722505],[-2.6635459,55.2192808],[-2.6460364,55.2188891],[-2.629042,55.2233933],[-2.6317886,55.2287781],[-2.6235488,55.2446345],[-2.6197723,55.2454663],[-2.6099017,55.2454174],[-2.6099876,55.2486466],[-2.6408121,55.2590039],[-2.6247896,55.2615631],[-2.6045186,55.2823081],[-2.5693176,55.296132],[-2.5479542,55.3121617],[-2.5091116,55.3234891],[-2.4780376,55.3494471],[-2.4421083,55.3533118],[-2.4052079,55.3439256],[-2.3726772,55.3447539],[-2.3221819,55.3687665],[-2.3241241,55.3999337],[-2.2576062,55.425015],[-2.1985547,55.4273529],[-2.1484296,55.4717466],[-2.1944348,55.484199],[-2.2040479,55.529306],[-2.2960584,55.6379722],[-2.2177808,55.6379722],[-2.1059266,55.7452498],[-1.9716874,55.7462161],[-1.9697453,55.9190951],[-2.1201694,55.9207115],[-2.1242893,55.9776133],[-2.3440159,55.9783817],[-2.3440159,56.0390349],[-2.5046909,56.0413363],[-2.500571,56.1003588],[-2.8823459,56.0957629],[-2.8823459,56.1722898],[-2.4126804,56.1692316],[-2.4181736,56.2334017],[-2.5857151,56.2303484],[-2.5719822,56.3416356],[-2.7257908,56.3462022],[-2.7312839,56.4343808],[-2.6928318,56.4343808],[-2.6928318,56.4859769],[-2.5307834,56.4935587],[-2.5307834,56.570806],[-2.5302878,56.6047947],[-2.3732428,56.6044452],[-2.3684363,56.7398824],[-2.3292975,56.7398824],[-2.3292975,56.7888065],[-2.3145346,56.7891826],[-2.3148779,56.7967036],[-2.171369,56.7967036],[-2.1703979,56.9710595],[-2.0101725,56.9694716],[-2.0101725,57.0846832],[-2.0817687,57.085349],[-2.0488097,57.1259963],[-2.0409133,57.126369],[-2.0383434,57.2411129],[-1.878118,57.2421638],[-1.8771469,57.2978175],[-1.9868771,57.2983422],[-1.9082209,57.3560063],[-1.8752048,57.3560063],[-1.8761758,57.3769527],[-1.8120857,57.4120111],[-1.7120661,57.4120111],[-1.7034646,57.6441388],[-1.8666032,57.6451781],[-1.8646611,57.7033351],[-3.1204292,57.7064705],[-3.1218025,57.7504652],[-3.4445259,57.7526635],[-3.4472724,57.7138067],[-3.5145637,57.7094052],[-3.5118171,57.6939956],[-3.7645027,57.6917938],[-3.7672492,57.6344975],[-3.842378,57.6288312],[-3.8438346,57.5965825],[-3.9414265,57.5916386],[-3.9404554,57.6537782],[-3.8894746,57.6529989],[-3.8826772,57.7676408],[-3.7224517,57.766087],[-3.7195385,57.8819201],[-3.9146888,57.8853352],[-3.916062,57.9546243],[-3.745774,57.9538956],[-3.7471473,58.0688409],[-3.5837256,58.0695672],[-3.5837256,58.1116689],[-3.4560096,58.1138452],[-3.4544646,58.228503],[-3.4379851,58.2283222],[-3.4243233,58.2427725],[-3.412307,58.2438567],[-3.3735115,58.2695057],[-3.3063919,58.2862038],[-3.1229154,58.2859395],[-3.123602,58.3443661],[-2.9574338,58.3447264],[-2.951254,58.6422011],[-2.8812162,58.6429157],[-2.8851004,58.8112825],[-2.7180775,58.8142997],[-2.7161354,58.8715749],[-2.556881,58.8775984],[-2.5544533,58.9923453],[-2.5567617,59.0483775],[-2.391893,59.0485996],[-2.3918002,59.1106996],[-2.4733695,59.1106996],[-2.5591563,59.1783028],[-2.5630406,59.2210646],[-2.3921334,59.224046],[-2.3911409,59.2740075],[-2.3639512,59.2745036],[-2.3658933,59.285417],[-2.3911409,59.284921],[-2.3911409,59.3379505],[-2.2221759,59.3381981],[-2.2233897,59.395965],[-2.3758467,59.396583],[-2.3899271,59.4026383],[-2.4008516,59.3962122],[-2.5637882,59.3952604],[-2.5637882,59.3385811],[-2.7320164,59.3375306],[-2.7333896,59.3952604],[-3.0726511,59.3931174],[-3.0703404,59.3354759],[-3.0753186,59.3355634],[-3.0749753,59.3292593],[-3.0698254,59.3289091],[-3.069801,59.2196159],[-3.2363384,59.2166341],[-3.2336751,59.1606496],[-3.4032766,59.1588895],[-3.394086,58.9279316],[-3.5664497,58.9259268],[-3.5611089,58.8679885],[-3.392508,58.8699339],[-3.3894734,58.8698711],[-3.3891093,58.8684905],[-3.3912942,58.868616],[-3.3884161,58.7543084],[-3.2238208,58.7555677],[-3.2189655,58.691289],[-3.4634113,58.6905753],[-3.4551716,58.6341518],[-3.787508,58.6341518],[-3.7861347,58.5769211],[-3.9028645,58.5733411],[-3.9028645,58.6477304],[-4.0690327,58.6491594],[-4.0690327,58.5912376],[-4.7364521,58.5933845],[-4.7364521,58.6505884],[-5.0715351,58.6520173],[-5.0654779,58.5325854],[-5.2332047,58.5316087],[-5.2283494,58.4719947],[-5.2424298,58.4719947],[-5.2366034,58.4089731],[-5.2283494,58.4094818],[-5.2210664,58.3005859],[-5.5657939,58.2959933],[-5.5580254,58.2372573],[-5.4146722,58.2401326],[-5.4141866,58.2267768],[-5.3885749,58.2272242],[-5.382714,58.1198615],[-5.51043,58.1191362],[-5.5114011,58.006214],[-5.6745397,58.0041559],[-5.6716266,57.9449366],[-5.6716266,57.8887166],[-5.8347652,57.8856193],[-5.8277052,57.5988958],[-6.0384259,57.5986357],[-6.0389115,57.6459559],[-6.1981658,57.6456961],[-6.2076123,57.7600132],[-6.537067,57.7544033],[-6.5312406,57.6402392],[-6.7002056,57.6360809],[-6.6807844,57.5236293],[-6.8516915,57.5152857],[-6.8361545,57.3385811],[-6.6730158,57.3438213],[-6.674958,57.2850883],[-6.5098772,57.2850883],[-6.4982244,57.1757637],[-6.3506228,57.1820797],[-6.3312015,57.1251969],[-6.1797156,57.1230884],[-6.1719471,57.0682265],[-6.4593819,57.059779],[-6.4564687,57.1093806],[-6.6671895,57.1062165],[-6.6730158,57.002708],[-6.5021087,57.0048233],[-6.4836097,56.8917522],[-6.3266104,56.8894062],[-6.3156645,56.7799312],[-6.2146739,56.775675],[-6.2146739,56.7234965],[-6.6866107,56.7224309],[-6.6769001,56.6114413],[-6.8419809,56.607166],[-6.8400387,56.5483307],[-7.1546633,56.5461895],[-7.1488369,56.4872592],[-6.9915246,56.490476],[-6.9876404,56.4325329],[-6.6827265,56.4314591],[-6.6769001,56.5472601],[-6.5292985,56.5504717],[-6.5234721,56.4379018],[-6.3661598,56.4368281],[-6.3642177,56.3766524],[-6.5273563,56.3712749],[-6.5171745,56.2428427],[-6.4869621,56.247421],[-6.4869621,56.1893882],[-6.3001945,56.1985572],[-6.3029411,56.2581017],[-5.9019401,56.256576],[-5.8964469,56.0960466],[-6.0282829,56.0883855],[-6.0392692,56.1557502],[-6.3853385,56.1542205],[-6.3606193,55.96099],[-6.2123039,55.9640647],[-6.2047508,55.9202269],[-6.5185478,55.9129158],[-6.5061881,55.7501763],[-6.6764762,55.7409005],[-6.6599967,55.6263176],[-6.3551261,55.6232161],[-6.3578727,55.5689002],[-6.0392692,55.5720059],[-6.0310294,55.6247669],[-5.7398917,55.6309694],[-5.7371452,55.4569279],[-5.8964469,55.4600426],[-5.8964469,55.2789864],[-5.4350211,55.2821151],[-5.4405143,55.4506979],[-5.2867057,55.4569279],[-5.3086784,55.4070602],[-4.9735954,55.4008223],[-4.9845817,55.2038242],[-5.1493766,55.2038242],[-5.1411369,55.037337],[-5.2152946,55.0341891],[-5.2112173,54.8018593]],[[-2.1646559,60.1622059],[-1.9930299,60.1609801],[-1.9946862,60.1035151],[-2.1663122,60.104743],[-2.1646559,60.1622059]],[[-1.5360658,59.8570831],[-1.3653566,59.8559841],[-1.366847,59.7975565],[-1.190628,59.7964199],[-1.1862046,59.9695391],[-1.0078652,59.9683948],[-1.0041233,60.114145],[-0.8360832,60.1130715],[-0.834574,60.1716772],[-1.0074262,60.1727795],[-1.0052165,60.2583924],[-0.8299659,60.2572778],[-0.826979,60.3726551],[-0.6507514,60.3715381],[-0.6477198,60.4882292],[-0.9984896,60.4904445],[-0.9970279,60.546555],[-0.6425288,60.5443201],[-0.6394896,60.6606792],[-0.8148133,60.6617806],[-0.8132987,60.7196112],[-0.6383298,60.7185141],[-0.635467,60.8275393],[-0.797568,60.8285523],[-0.9941426,60.8297807],[-0.9954966,60.7782667],[-1.1670282,60.7793403],[-1.1700357,60.6646181],[-1.5222599,60.6668304],[-1.5237866,60.6084426],[-1.6975673,60.609536],[-1.7021271,60.4345249],[-1.5260578,60.4334111],[-1.5275203,60.3770719],[-1.8751127,60.3792746],[-1.8781372,60.2624647],[-1.7019645,60.2613443],[-1.7049134,60.1470532],[-1.528659,60.1459283],[-1.5360658,59.8570831]],[[-0.9847667,60.8943762],[-0.9860347,60.8361105],[-0.8078362,60.8351904],[-0.8065683,60.8934578],[-0.9847667,60.8943762]],[[-7.7696901,56.8788231],[-7.7614504,56.7608274],[-7.6009049,56.7641903],[-7.5972473,56.819332],[-7.4479894,56.8203948],[-7.4489319,56.8794098],[-7.2841369,56.8794098],[-7.2813904,57.0471152],[-7.1303283,57.0515969],[-7.1330749,57.511801],[-6.96828,57.5147514],[-6.9765198,57.6854668],[-6.8062317,57.6913392],[-6.8089782,57.8041985],[-6.6496765,57.8071252],[-6.6441833,57.8612267],[-6.3200866,57.8626878],[-6.3200866,58.1551617],[-6.1607849,58.1522633],[-6.1552917,58.20874],[-5.9850036,58.2101869],[-5.9904968,58.2680163],[-6.1497986,58.2665717],[-6.1415588,58.5557514],[-6.3173401,58.5557514],[-6.3091003,58.4983923],[-6.4876282,58.4955218],[-6.4876282,58.4423768],[-6.6606628,58.4395018],[-6.6469299,58.3819525],[-6.8117248,58.3805125],[-6.8117248,58.3286357],[-6.9792663,58.3286357],[-6.9710266,58.2694608],[-7.1413147,58.2680163],[-7.1403816,58.0358742],[-7.3020636,58.0351031],[-7.3030347,57.9774797],[-7.1379539,57.9777372],[-7.1413526,57.9202792],[-7.1398961,57.8640206],[-7.3020636,57.862471],[-7.298484,57.7442293],[-7.4509193,57.7456951],[-7.4550392,57.6899522],[-7.6186131,57.6906048],[-7.6198341,57.7456951],[-7.7901222,57.7442293],[-7.7873756,57.6855477],[-7.6222332,57.6853817],[-7.6173779,57.5712602],[-7.788285,57.5709998],[-7.7892561,57.512109],[-7.7038025,57.5115874],[-7.6999183,57.4546902],[-7.5367796,57.4552126],[-7.5348375,57.5126306],[-7.4581235,57.5131521],[-7.4552103,57.2824165],[-7.6115515,57.2845158],[-7.6144647,57.2272651],[-7.451326,57.2256881],[-7.451326,57.1103873],[-7.6164068,57.1088053],[-7.603783,56.8792358],[-7.7696901,56.8788231]],[[-1.7106618,59.5626284],[-1.5417509,59.562215],[-1.5423082,59.5037224],[-1.7112191,59.5041365],[-1.7106618,59.5626284]]],"terms_url":"http://geo.nls.uk/maps/","terms_text":"National Library of Scotland Historic Maps"},{"name":"OpenPT Map (overlay)","type":"tms","template":"http://openptmap.de/tiles/{zoom}/{x}/{y}.png","scaleExtent":[4,17],"terms_url":"http://openstreetmap.org/","terms_text":"© OpenStreetMap contributors, CC-BY-SA","overlay":true},{"name":"OpenStreetMap (Standard)","type":"tms","description":"The default OpenStreetMap layer.","template":"http://{switch:a,b,c}.tile.openstreetmap.org/{zoom}/{x}/{y}.png","scaleExtent":[0,19],"terms_url":"http://openstreetmap.org/","terms_text":"© OpenStreetMap contributors, CC-BY-SA","id":"MAPNIK","default":true},{"name":"OpenStreetMap GPS traces","type":"tms","description":"Public GPS traces uploaded to OpenStreetMap.","template":"http://{switch:a,b,c}.gps-tile.openstreetmap.org/lines/{zoom}/{x}/{y}.png","scaleExtent":[0,20],"terms_url":"http://www.openstreetmap.org/copyright","terms_text":"© OpenStreetMap contributors","terms_html":"<span style='display: inline-block; padding: 0 8px; background-color: rgba(0,0,0,0.5);'><span style='color: #eee;'>GPS Direction:</span> <span style='font-size: 15px; padding-left: 2px; font-weight: bold;'> <span style='color: #0ee;'>&larr;</span> <span style='color: #96f;'>&darr;</span> <span style='color: #6e0;'>&uarr;</span> <span style='color: #f63;'>&rarr;</span> </span></span> © <a href='http://www.openstreetmap.org/copyright'>OpenStreetMap contributors</a>.","overlay":true},{"name":"OS 1:25k historic (OSM)","type":"tms","template":"http://ooc.openstreetmap.org/os1/{zoom}/{x}/{y}.jpg","scaleExtent":[6,17],"polygon":[[[-9,49.8],[-9,61.1],[1.9,61.1],[1.9,49.8],[-9,49.8]]]},{"name":"OS New Popular Edition historic","type":"tms","template":"http://ooc.openstreetmap.org/npe/{zoom}/{x}/{y}.png","polygon":[[[-5.8,49.8],[-5.8,55.8],[1.9,55.8],[1.9,49.8],[-5.8,49.8]]]},{"name":"OS OpenData Locator","type":"tms","template":"http://tiles.itoworld.com/os_locator/{zoom}/{x}/{y}.png","polygon":[[[-9,49.8],[-9,61.1],[1.9,61.1],[1.9,49.8],[-9,49.8]]],"overlay":true},{"name":"OS OpenData StreetView","type":"tms","template":"http://os.openstreetmap.org/sv/{zoom}/{x}/{y}.png","scaleExtent":[1,18],"polygon":[[[-5.8292886,50.0229734],[-5.8292886,50.254819],[-5.373356,50.254819],[-5.373356,50.3530588],[-5.1756021,50.3530588],[-5.1756021,50.5925406],[-4.9970743,50.5925406],[-4.9970743,50.6935617],[-4.7965738,50.6935617],[-4.7965738,50.7822112],[-4.6949503,50.7822112],[-4.6949503,50.9607371],[-4.6043131,50.9607371],[-4.6043131,51.0692066],[-4.3792215,51.0692066],[-4.3792215,51.2521782],[-3.9039346,51.2521782],[-3.9039346,51.2916998],[-3.7171671,51.2916998],[-3.7171671,51.2453014],[-3.1486246,51.2453014],[-3.1486246,51.362067],[-3.7446329,51.362067],[-3.7446329,51.4340386],[-3.8297769,51.4340386],[-3.8297769,51.5298246],[-4.0852091,51.5298246],[-4.0852091,51.4939284],[-4.3792215,51.4939284],[-4.3792215,51.5427168],[-5.1444195,51.5427168],[-5.1444195,51.6296003],[-5.7387103,51.6296003],[-5.7387103,51.774037],[-5.5095393,51.774037],[-5.5095393,51.9802596],[-5.198799,51.9802596],[-5.198799,52.0973358],[-4.8880588,52.0973358],[-4.8880588,52.1831557],[-4.4957492,52.1831557],[-4.4957492,52.2925739],[-4.3015365,52.2925739],[-4.3015365,52.3685318],[-4.1811246,52.3685318],[-4.1811246,52.7933685],[-4.4413696,52.7933685],[-4.4413696,52.7369614],[-4.8569847,52.7369614],[-4.8569847,52.9317255],[-4.7288044,52.9317255],[-4.7288044,53.5038599],[-4.1578191,53.5038599],[-4.1578191,53.4113498],[-3.3110518,53.4113498],[-3.3110518,53.5038599],[-3.2333667,53.5038599],[-3.2333667,54.0159169],[-3.3926211,54.0159169],[-3.3926211,54.1980953],[-3.559644,54.1980953],[-3.559644,54.433732],[-3.7188984,54.433732],[-3.7188984,54.721897],[-4.3015365,54.721897],[-4.3015365,54.6140739],[-5.0473132,54.6140739],[-5.0473132,54.7532915],[-5.2298731,54.7532915],[-5.2298731,55.2190799],[-5.6532567,55.2190799],[-5.6532567,55.250088],[-5.8979647,55.250088],[-5.8979647,55.4822462],[-6.5933212,55.4822462],[-6.5933212,56.3013441],[-7.1727691,56.3013441],[-7.1727691,56.5601822],[-6.8171722,56.5601822],[-6.8171722,56.6991713],[-6.5315276,56.6991713],[-6.5315276,56.9066964],[-6.811679,56.9066964],[-6.811679,57.3716613],[-6.8721038,57.3716613],[-6.8721038,57.5518893],[-7.0973235,57.5518893],[-7.0973235,57.2411085],[-7.1742278,57.2411085],[-7.1742278,56.9066964],[-7.3719817,56.9066964],[-7.3719817,56.8075885],[-7.5202972,56.8075885],[-7.5202972,56.7142479],[-7.8306806,56.7142479],[-7.8306806,56.8994605],[-7.6494061,56.8994605],[-7.6494061,57.4739617],[-7.8306806,57.4739617],[-7.8306806,57.7915584],[-7.4736249,57.7915584],[-7.4736249,58.086063],[-7.1879804,58.086063],[-7.1879804,58.367197],[-6.8034589,58.367197],[-6.8034589,58.4155786],[-6.638664,58.4155786],[-6.638664,58.4673277],[-6.5178143,58.4673277],[-6.5178143,58.5625632],[-6.0536224,58.5625632],[-6.0536224,58.1568843],[-6.1470062,58.1568843],[-6.1470062,58.1105865],[-6.2799798,58.1105865],[-6.2799798,57.7122664],[-6.1591302,57.7122664],[-6.1591302,57.6667563],[-5.9339104,57.6667563],[-5.9339104,57.8892524],[-5.80643,57.8892524],[-5.80643,57.9621767],[-5.6141692,57.9621767],[-5.6141692,58.0911236],[-5.490819,58.0911236],[-5.490819,58.3733281],[-5.3199118,58.3733281],[-5.3199118,58.75015],[-3.5719977,58.75015],[-3.5719977,59.2091788],[-3.1944501,59.2091788],[-3.1944501,59.4759216],[-2.243583,59.4759216],[-2.243583,59.1388749],[-2.4611012,59.1388749],[-2.4611012,58.8185938],[-2.7407675,58.8185938],[-2.7407675,58.5804743],[-2.9116746,58.5804743],[-2.9116746,58.1157523],[-3.4865441,58.1157523],[-3.4865441,57.740386],[-1.7153245,57.740386],[-1.7153245,57.2225558],[-1.9794538,57.2225558],[-1.9794538,56.8760742],[-2.1658979,56.8760742],[-2.1658979,56.6333186],[-2.3601106,56.6333186],[-2.3601106,56.0477521],[-1.9794538,56.0477521],[-1.9794538,55.8650949],[-1.4745008,55.8650949],[-1.4745008,55.2499926],[-1.3221997,55.2499926],[-1.3221997,54.8221737],[-1.0550014,54.8221737],[-1.0550014,54.6746628],[-0.6618765,54.6746628],[-0.6618765,54.5527463],[-0.3247617,54.5527463],[-0.3247617,54.2865195],[0.0092841,54.2865195],[0.0092841,53.7938518],[0.2081962,53.7938518],[0.2081962,53.5217726],[0.4163548,53.5217726],[0.4163548,53.0298851],[1.4273388,53.0298851],[1.4273388,52.92021],[1.8333912,52.92021],[1.8333912,52.042488],[1.5235504,52.042488],[1.5235504,51.8261335],[1.2697049,51.8261335],[1.2697049,51.6967453],[1.116651,51.6967453],[1.116651,51.440346],[1.5235504,51.440346],[1.5235504,51.3331831],[1.4507565,51.3331831],[1.4507565,51.0207553],[1.0699883,51.0207553],[1.0699883,50.9008416],[0.7788126,50.9008416],[0.7788126,50.729843],[-0.7255952,50.729843],[-0.7255952,50.7038437],[-1.0074383,50.7038437],[-1.0074383,50.5736307],[-2.3625252,50.5736307],[-2.3625252,50.4846421],[-2.4987805,50.4846421],[-2.4987805,50.5736307],[-3.4096378,50.5736307],[-3.4096378,50.2057837],[-3.6922446,50.2057837],[-3.6922446,50.1347737],[-5.005468,50.1347737],[-5.005468,49.9474456],[-5.2839506,49.9474456],[-5.2839506,50.0229734],[-5.8292886,50.0229734]],[[-6.4580707,49.8673563],[-6.4580707,49.9499935],[-6.3978807,49.9499935],[-6.3978807,50.0053797],[-6.1799606,50.0053797],[-6.1799606,49.9168614],[-6.2540201,49.9168614],[-6.2540201,49.8673563],[-6.4580707,49.8673563]],[[-5.8343165,49.932156],[-5.8343165,49.9754641],[-5.7683254,49.9754641],[-5.7683254,49.932156],[-5.8343165,49.932156]],[[-1.9483797,60.6885737],[-1.9483797,60.3058841],[-1.7543149,60.3058841],[-1.7543149,60.1284428],[-1.5754914,60.1284428],[-1.5754914,59.797917],[-1.0316959,59.797917],[-1.0316959,60.0354518],[-0.6626918,60.0354518],[-0.6626918,60.9103862],[-1.1034395,60.9103862],[-1.1034395,60.8040022],[-1.3506319,60.8040022],[-1.3506319,60.6885737],[-1.9483797,60.6885737]],[[-2.203381,60.1968568],[-2.203381,60.0929443],[-1.9864011,60.0929443],[-1.9864011,60.1968568],[-2.203381,60.1968568]],[[-1.7543149,59.5698289],[-1.7543149,59.4639383],[-1.5373349,59.4639383],[-1.5373349,59.5698289],[-1.7543149,59.5698289]],[[-4.5585981,59.1370518],[-4.5585981,58.9569099],[-4.2867004,58.9569099],[-4.2867004,59.1370518],[-4.5585981,59.1370518]],[[-6.2787732,59.2025744],[-6.2787732,59.0227769],[-5.6650612,59.0227769],[-5.6650612,59.2025744],[-6.2787732,59.2025744]],[[-8.7163482,57.9440556],[-8.7163482,57.7305936],[-8.3592926,57.7305936],[-8.3592926,57.9440556],[-8.7163482,57.9440556]],[[-7.6077005,50.4021026],[-7.6077005,50.2688657],[-7.3907205,50.2688657],[-7.3907205,50.4021026],[-7.6077005,50.4021026]],[[-7.7304303,58.3579902],[-7.7304303,58.248313],[-7.5134503,58.248313],[-7.5134503,58.3579902],[-7.7304303,58.3579902]]]},{"name":"OS Scottish Popular historic","type":"tms","template":"http://ooc.openstreetmap.org/npescotland/tiles/{zoom}/{x}/{y}.jpg","scaleExtent":[6,15],"polygon":[[[-7.8,54.5],[-7.8,61.1],[-1.1,61.1],[-1.1,54.5],[-7.8,54.5]]]},{"name":"OSM Inspector: Addresses","type":"tms","template":"http://tools.geofabrik.de/osmi/tiles/addresses/{zoom}/{x}/{y}.png","scaleExtent":[0,18],"terms_url":"http://tools.geofabrik.de/osmi/","terms_text":"© Geofabrik GmbH, OpenStreetMap contributors, CC-BY-SA","overlay":true},{"name":"OSM Inspector: Routing","type":"tms","template":"http://tools.geofabrik.de/osmi/tiles/routing/{zoom}/{x}/{y}.png","scaleExtent":[0,18],"terms_url":"http://tools.geofabrik.de/osmi/","terms_text":"© Geofabrik GmbH, OpenStreetMap contributors, CC-BY-SA","overlay":true},{"name":"Pangasinán/Bulacan (Phillipines HiRes)","type":"tms","template":"http://gravitystorm.dev.openstreetmap.org/imagery/philippines/{zoom}/{x}/{y}.png","scaleExtent":[12,19],"polygon":[[[120.336593,15.985768],[120.445995,15.984],[120.446134,15.974459],[120.476464,15.974592],[120.594247,15.946832],[120.598064,16.090795],[120.596537,16.197999],[120.368537,16.218527],[120.347576,16.042308],[120.336593,15.985768]],[[120.8268,15.3658],[121.2684,15.2602],[121.2699,14.7025],[120.695,14.8423],[120.8268,15.3658]]]},{"name":"Slovakia EEA CORINE 2006","type":"tms","template":"http://www.freemap.sk/tms/clc/{zoom}/{x}/{y}.png","polygon":[[[19.83682,49.25529],[19.80075,49.42385],[19.60437,49.48058],[19.49179,49.63961],[19.21831,49.52604],[19.16778,49.42521],[19.00308,49.42236],[18.97611,49.5308],[18.54685,49.51425],[18.31432,49.33818],[18.15913,49.2961],[18.05564,49.11134],[17.56396,48.84938],[17.17929,48.88816],[17.058,48.81105],[16.90426,48.61947],[16.79685,48.38561],[17.06762,48.01116],[17.32787,47.97749],[17.51699,47.82535],[17.74776,47.73093],[18.29515,47.72075],[18.67959,47.75541],[18.89755,47.81203],[18.79463,47.88245],[18.84318,48.04046],[19.46212,48.05333],[19.62064,48.22938],[19.89585,48.09387],[20.33766,48.2643],[20.55395,48.52358],[20.82335,48.55714],[21.10271,48.47096],[21.45863,48.55513],[21.74536,48.31435],[22.15293,48.37179],[22.61255,49.08914],[22.09997,49.23814],[21.9686,49.36363],[21.6244,49.46989],[21.06873,49.46402],[20.94336,49.31088],[20.73052,49.44006],[20.22804,49.41714],[20.05234,49.23052],[19.83682,49.25529]]],"terms_url":"http://www.eea.europa.eu/data-and-maps/data/clc-2006-vector-data-version-1","terms_text":"EEA Corine 2006"},{"name":"Slovakia EEA GMES Urban Atlas","type":"tms","template":"http://www.freemap.sk/tms/urbanatlas/{zoom}/{x}/{y}.png","polygon":[[[19.83682,49.25529],[19.80075,49.42385],[19.60437,49.48058],[19.49179,49.63961],[19.21831,49.52604],[19.16778,49.42521],[19.00308,49.42236],[18.97611,49.5308],[18.54685,49.51425],[18.31432,49.33818],[18.15913,49.2961],[18.05564,49.11134],[17.56396,48.84938],[17.17929,48.88816],[17.058,48.81105],[16.90426,48.61947],[16.79685,48.38561],[17.06762,48.01116],[17.32787,47.97749],[17.51699,47.82535],[17.74776,47.73093],[18.29515,47.72075],[18.67959,47.75541],[18.89755,47.81203],[18.79463,47.88245],[18.84318,48.04046],[19.46212,48.05333],[19.62064,48.22938],[19.89585,48.09387],[20.33766,48.2643],[20.55395,48.52358],[20.82335,48.55714],[21.10271,48.47096],[21.45863,48.55513],[21.74536,48.31435],[22.15293,48.37179],[22.61255,49.08914],[22.09997,49.23814],[21.9686,49.36363],[21.6244,49.46989],[21.06873,49.46402],[20.94336,49.31088],[20.73052,49.44006],[20.22804,49.41714],[20.05234,49.23052],[19.83682,49.25529]]],"terms_url":"http://www.eea.europa.eu/data-and-maps/data/urban-atlas","terms_text":"EEA GMES Urban Atlas"},{"name":"Slovakia Historic Maps","type":"tms","template":"http://tms.freemap.sk/historicke/{zoom}/{x}/{y}.png","scaleExtent":[0,12],"polygon":[[[16.8196949,47.4927236],[16.8196949,49.5030322],[22.8388318,49.5030322],[22.8388318,47.4927236],[16.8196949,47.4927236]]]},{"name":"South Africa CD:NGI Aerial","type":"tms","template":"http://{switch:a,b,c}.aerial.openstreetmap.org.za/ngi-aerial/{zoom}/{x}/{y}.jpg","scaleExtent":[1,22],"polygon":[[[17.8396817,-32.7983384],[17.8893509,-32.6972835],[18.00364,-32.6982187],[18.0991679,-32.7485251],[18.2898747,-32.5526645],[18.2930182,-32.0487089],[18.105455,-31.6454966],[17.8529257,-31.3443951],[17.5480046,-30.902171],[17.4044506,-30.6374731],[17.2493704,-30.3991663],[16.9936977,-29.6543552],[16.7987996,-29.19437],[16.5494139,-28.8415949],[16.4498691,-28.691876],[16.4491046,-28.5515766],[16.6002551,-28.4825663],[16.7514057,-28.4486958],[16.7462192,-28.2458973],[16.8855148,-28.04729],[16.9929502,-28.0244005],[17.0529659,-28.0257086],[17.1007562,-28.0338839],[17.2011527,-28.0930546],[17.2026346,-28.2328424],[17.2474611,-28.2338215],[17.2507953,-28.198892],[17.3511919,-28.1975861],[17.3515624,-28.2442655],[17.4015754,-28.2452446],[17.4149122,-28.3489751],[17.4008345,-28.547997],[17.4526999,-28.5489733],[17.4512071,-28.6495106],[17.4983599,-28.6872054],[17.6028204,-28.6830048],[17.6499732,-28.6967928],[17.6525928,-28.7381457],[17.801386,-28.7381457],[17.9994276,-28.7560602],[18.0002748,-28.7956172],[18.1574507,-28.8718055],[18.5063811,-28.8718055],[18.6153564,-28.8295875],[18.9087513,-28.8277516],[19.1046973,-28.9488548],[19.1969071,-28.9378513],[19.243012,-28.8516164],[19.2314858,-28.802963],[19.2587296,-28.7009928],[19.4431493,-28.6973163],[19.5500289,-28.4958332],[19.6967264,-28.4939914],[19.698822,-28.4479358],[19.8507587,-28.4433291],[19.8497109,-28.4027818],[19.9953605,-28.399095],[19.9893671,-24.7497859],[20.2916682,-24.9192346],[20.4724562,-25.1501701],[20.6532441,-25.4529449],[20.733265,-25.6801957],[20.8281046,-25.8963498],[20.8429232,-26.215851],[20.6502804,-26.4840868],[20.6532441,-26.8204869],[21.0889134,-26.846933],[21.6727695,-26.8389998],[21.7765003,-26.6696268],[21.9721069,-26.6431395],[22.2803355,-26.3274702],[22.5707817,-26.1333967],[22.7752795,-25.6775246],[23.0005235,-25.2761948],[23.4658301,-25.2735148],[23.883717,-25.597366],[24.2364017,-25.613402],[24.603905,-25.7896563],[25.110704,-25.7389432],[25.5078447,-25.6855376],[25.6441766,-25.4823781],[25.8419267,-24.7805437],[25.846641,-24.7538456],[26.3928487,-24.6332894],[26.4739066,-24.5653312],[26.5089966,-24.4842437],[26.5861946,-24.4075775],[26.7300635,-24.3014458],[26.8567384,-24.2499463],[26.8574402,-24.1026901],[26.9215471,-23.8990957],[26.931831,-23.8461891],[26.9714827,-23.6994344],[27.0006074,-23.6367644],[27.0578041,-23.6052574],[27.1360547,-23.5203437],[27.3339623,-23.3973792],[27.5144057,-23.3593929],[27.5958145,-23.2085465],[27.8098634,-23.0994957],[27.8828506,-23.0620496],[27.9382928,-22.9496487],[28.0407556,-22.8255118],[28.2056786,-22.6552861],[28.3397223,-22.5639374],[28.4906093,-22.560697],[28.6108769,-22.5400248],[28.828175,-22.4550173],[28.9285324,-22.4232328],[28.9594116,-22.3090081],[29.0162574,-22.208335],[29.2324117,-22.1693453],[29.3531213,-22.1842926],[29.6548952,-22.1186426],[29.7777102,-22.1361956],[29.9292989,-22.1849425],[30.1166795,-22.2830348],[30.2563377,-22.2914767],[30.3033582,-22.3395204],[30.5061784,-22.3057617],[30.8374279,-22.284983],[31.0058599,-22.3077095],[31.1834152,-22.3232913],[31.2930586,-22.3674647],[31.5680579,-23.1903385],[31.5568311,-23.4430809],[31.6931122,-23.6175209],[31.7119696,-23.741136],[31.7774743,-23.8800628],[31.8886337,-23.9481098],[31.9144386,-24.1746736],[31.9948307,-24.3040878],[32.0166656,-24.4405988],[32.0077331,-24.6536578],[32.019643,-24.9140701],[32.035523,-25.0849767],[32.019643,-25.3821442],[31.9928457,-25.4493771],[31.9997931,-25.5165725],[32.0057481,-25.6078978],[32.0057481,-25.6624806],[31.9362735,-25.8403721],[31.9809357,-25.9546537],[31.8687838,-26.0037251],[31.4162062,-25.7277683],[31.3229117,-25.7438611],[31.2504595,-25.8296526],[31.1393001,-25.9162746],[31.1164727,-25.9912361],[30.9656135,-26.2665756],[30.8921689,-26.3279703],[30.8534616,-26.4035568],[30.8226943,-26.4488849],[30.8022583,-26.5240694],[30.8038369,-26.8082089],[30.9020939,-26.7807451],[30.9100338,-26.8489495],[30.9824859,-26.9082627],[30.976531,-27.0029222],[31.0034434,-27.0441587],[31.1543322,-27.1980416],[31.5015607,-27.311117],[31.9700183,-27.311117],[31.9700183,-27.120472],[31.9769658,-27.050664],[32.0002464,-26.7983892],[32.1069826,-26.7984645],[32.3114546,-26.8479493],[32.899986,-26.8516059],[32.886091,-26.9816971],[32.709427,-27.4785436],[32.6240724,-27.7775144],[32.5813951,-28.07479],[32.5387178,-28.2288046],[32.4275584,-28.5021568],[32.3640388,-28.5945699],[32.0702603,-28.8469827],[31.9878832,-28.9069497],[31.7764818,-28.969487],[31.4638459,-29.2859343],[31.359634,-29.3854348],[31.1680825,-29.6307408],[31.064863,-29.7893535],[31.0534493,-29.8470469],[31.0669933,-29.8640319],[31.0455459,-29.9502017],[30.9518556,-30.0033946],[30.8651833,-30.1024093],[30.7244725,-30.392502],[30.3556256,-30.9308873],[30.0972364,-31.2458274],[29.8673136,-31.4304296],[29.7409393,-31.5014699],[29.481312,-31.6978686],[28.8943171,-32.2898903],[28.5497137,-32.5894641],[28.1436499,-32.8320732],[28.0748735,-32.941689],[27.8450942,-33.082869],[27.3757956,-33.3860685],[26.8805407,-33.6458951],[26.5916871,-33.7480756],[26.4527308,-33.7935795],[26.206754,-33.7548943],[26.0077897,-33.7223961],[25.8055494,-33.7524272],[25.7511073,-33.8006512],[25.6529079,-33.8543597],[25.6529079,-33.9469768],[25.7195789,-34.0040115],[25.7202807,-34.0511235],[25.5508915,-34.063151],[25.3504571,-34.0502627],[25.2810609,-34.0020322],[25.0476316,-33.9994588],[24.954724,-34.0043594],[24.9496586,-34.1010363],[24.8770358,-34.1506456],[24.8762914,-34.2005281],[24.8532574,-34.2189562],[24.7645287,-34.2017946],[24.5001356,-34.2003254],[24.3486733,-34.1163824],[24.1988819,-34.1019039],[23.9963377,-34.0514443],[23.8017509,-34.0524332],[23.7493589,-34.0111855],[23.4973536,-34.009014],[23.4155191,-34.0434586],[23.4154284,-34.1140433],[22.9000853,-34.0993009],[22.8412418,-34.0547911],[22.6470321,-34.0502627],[22.6459843,-34.0072768],[22.570016,-34.0064081],[22.5050499,-34.0645866],[22.2519968,-34.0645866],[22.2221334,-34.1014701],[22.1621197,-34.1057019],[22.1712431,-34.1521766],[22.1576913,-34.2180897],[22.0015632,-34.2172232],[21.9496952,-34.3220009],[21.8611528,-34.4007145],[21.5614708,-34.4020114],[21.5468011,-34.3661242],[21.501744,-34.3669892],[21.5006961,-34.4020114],[21.4194886,-34.4465247],[21.1978706,-34.4478208],[21.0988193,-34.3991325],[21.0033746,-34.3753872],[20.893192,-34.3997115],[20.8976647,-34.4854003],[20.7446802,-34.4828092],[20.5042011,-34.486264],[20.2527197,-34.701477],[20.0803502,-34.8361855],[19.9923317,-34.8379056],[19.899074,-34.8275845],[19.8938348,-34.7936018],[19.5972963,-34.7961833],[19.3929677,-34.642015],[19.2877095,-34.6404784],[19.2861377,-34.5986563],[19.3474363,-34.5244458],[19.3285256,-34.4534372],[19.098001,-34.449981],[19.0725583,-34.3802371],[19.0023531,-34.3525593],[18.9520568,-34.3949373],[18.7975006,-34.3936403],[18.7984174,-34.1016376],[18.501748,-34.1015292],[18.4999545,-34.3616945],[18.4477325,-34.3620007],[18.4479944,-34.3522691],[18.3974362,-34.3514041],[18.3971742,-34.3022959],[18.3565705,-34.3005647],[18.3479258,-34.2020436],[18.2972095,-34.1950274],[18.2951139,-33.9937138],[18.3374474,-33.9914079],[18.3476638,-33.8492427],[18.3479258,-33.781555],[18.4124718,-33.7448849],[18.3615477,-33.6501624],[18.2992013,-33.585591],[18.2166839,-33.448872],[18.1389858,-33.3974083],[17.9473472,-33.1602647],[17.8855247,-33.0575732],[17.8485884,-32.9668505],[17.8396817,-32.8507302],[17.8396817,-32.7983384]]],"best":true},{"name":"South Tyrol Orthofoto 2011","type":"tms","description":"Orthophoto of South Tyrol from 2011","template":"http://geoservices.buergernetz.bz.it/geoserver/gwc/service/wmts/?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=P_BZ_OF_2011_EPSG3857&STYLE=default&TILEMATRIXSET=GoogleMapsCompatible&TILEMATRIX=GoogleMapsCompatible%3A{zoom}&TILEROW={y}&TILECOL={x}&FORMAT=image%2Fjpeg","scaleExtent":[0,18],"polygon":[[[10.38615,46.68821],[10.39201,46.69016],[10.40215,46.70624],[10.41274,46.70821],[10.41622,46.71479],[10.4168,46.71847],[10.39934,46.73435],[10.43464,46.75356],[10.44107,46.75413],[10.44011,46.77149],[10.42123,46.78861],[10.42845,46.79755],[10.43851,46.79869],[10.44925,46.80462],[10.45602,46.81635],[10.45438,46.82221],[10.4583,46.82478],[10.45513,46.83059],[10.45906,46.83548],[10.46483,46.83624],[10.46229,46.8413],[10.46987,46.84933],[10.46819,46.8553],[10.47838,46.86013],[10.48372,46.85543],[10.49628,46.85305],[10.49931,46.84857],[10.52124,46.84653],[10.5527,46.8511],[10.55795,46.84695],[10.55264,46.8408],[10.55536,46.84087],[10.58883,46.85125],[10.59502,46.85829],[10.60936,46.8597],[10.62441,46.86558],[10.64858,46.86655],[10.66787,46.87651],[10.67297,46.87138],[10.69112,46.86861],[10.69786,46.86339],[10.69508,46.85308],[10.70594,46.84786],[10.71763,46.84795],[10.72333,46.83892],[10.75621,46.83383],[10.76481,46.82409],[10.76387,46.81971],[10.75239,46.81387],[10.74506,46.80223],[10.7276,46.79709],[10.73122,46.78925],[10.75722,46.78624],[10.77744,46.79149],[10.78678,46.79735],[10.81439,46.77662],[10.82479,46.77472],[10.83129,46.78138],[10.84112,46.78282],[10.85354,46.77506],[10.86845,46.77313],[10.86993,46.7669],[10.88294,46.76393],[10.88962,46.76529],[10.8951,46.77092],[10.90527,46.76911],[10.92299,46.7764],[10.92821,46.77408],[10.94388,46.77648],[10.97522,46.77361],[10.97932,46.77014],[10.99475,46.76804],[11.01397,46.77317],[11.02328,46.76715],[11.0346,46.79428],[11.04234,46.801],[11.03792,46.80562],[11.05633,46.80928],[11.07279,46.82092],[11.08171,46.82252],[11.0762,46.83384],[11.06887,46.83793],[11.07303,46.84345],[11.06988,46.85348],[11.08742,46.87927],[11.09961,46.88922],[11.09538,46.89178],[11.09795,46.89844],[11.0946,46.91247],[11.10792,46.91706],[11.10804,46.92632],[11.11418,46.93234],[11.13851,46.92865],[11.16322,46.94091],[11.16642,46.94479],[11.16114,46.94979],[11.1637,46.96677],[11.17598,46.96367],[11.18658,46.97062],[11.19527,46.97152],[11.20418,46.96877],[11.20688,46.96403],[11.22047,46.97025],[11.24139,46.9708],[11.24865,46.97517],[11.25582,46.97535],[11.26272,46.98169],[11.27662,46.98168],[11.28762,46.98699],[11.30709,46.98525],[11.3205,46.99345],[11.33765,46.98606],[11.34516,46.99169],[11.35932,46.99154],[11.37697,46.98025],[11.38324,46.97168],[11.40465,46.96609],[11.43929,46.97601],[11.45134,46.99294],[11.46803,46.99582],[11.46859,47.003],[11.47831,47.01201],[11.50238,47.01073],[11.50313,47.00808],[11.51366,47.00595],[11.51679,47.00091],[11.53381,46.99233],[11.53846,46.98519],[11.55297,46.99149],[11.57663,46.99657],[11.58,47.00277],[11.58879,47.00641],[11.59901,47.00657],[11.60944,47.01207],[11.62697,47.01437],[11.63629,47.00383],[11.66542,46.99304],[11.6885,46.99658],[11.71226,46.99416],[11.72897,46.97322],[11.74698,46.97013],[11.76411,46.97412],[11.78106,46.99342],[11.81526,46.991],[11.83564,46.99417],[11.84396,47.0025],[11.85192,47.0014],[11.86722,47.01252],[11.87393,47.01136],[11.8794,47.01714],[11.89137,47.01728],[11.91627,47.03422],[11.9329,47.03864],[11.94688,47.03464],[11.95457,47.04374],[11.96773,47.04158],[11.97912,47.0511],[11.98587,47.04815],[11.99534,47.05064],[12.02037,47.04821],[12.02968,47.05127],[12.03353,47.0583],[12.04276,47.06228],[12.07543,47.0605],[12.08035,47.06951],[12.09308,47.07791],[12.10329,47.07931],[12.11867,47.07445],[12.13561,47.08171],[12.15125,47.08049],[12.15997,47.08267],[12.18589,47.09322],[12.2278,47.08302],[12.24228,47.06892],[12.23786,47.0644],[12.21821,47.05795],[12.2182,47.04483],[12.20552,47.02595],[12.18048,47.02414],[12.16423,47.01782],[12.14786,47.02357],[12.12723,47.01218],[12.12285,47.00662],[12.1322,46.99339],[12.12974,46.98593],[12.13977,46.982],[12.13808,46.96514],[12.13328,46.96292],[12.13882,46.95764],[12.15927,46.95133],[12.1702,46.93758],[12.15414,46.91654],[12.14675,46.91413],[12.16205,46.908],[12.16959,46.91121],[12.19154,46.90682],[12.20106,46.8965],[12.2022,46.88806],[12.21663,46.87517],[12.22147,46.88084],[12.23125,46.88146],[12.2345,46.88919],[12.24162,46.89192],[12.27486,46.88512],[12.27979,46.87921],[12.27736,46.87319],[12.29326,46.86566],[12.2912,46.85704],[12.29733,46.84455],[12.30833,46.84137],[12.30726,46.83271],[12.285,46.81503],[12.29383,46.8027],[12.28905,46.79948],[12.28889,46.79427],[12.28232,46.79153],[12.28539,46.7839],[12.30943,46.78603],[12.35837,46.77583],[12.37036,46.74163],[12.38475,46.71745],[12.40283,46.70811],[12.41103,46.70701],[12.41522,46.70163],[12.42862,46.6997],[12.42943,46.69567],[12.44268,46.68979],[12.47501,46.68756],[12.4795,46.67969],[12.43473,46.66714],[12.40648,46.64167],[12.38115,46.64183],[12.37944,46.63733],[12.3915,46.62765],[12.38577,46.62154],[12.35939,46.61829],[12.34465,46.62376],[12.34034,46.63022],[12.33578,46.62732],[12.3172,46.62876],[12.31785,46.62355],[12.30802,46.61811],[12.28413,46.61623],[12.26982,46.62003],[12.25931,46.62809],[12.24502,46.62326],[12.24198,46.61586],[12.21241,46.60918],[12.20444,46.59836],[12.19228,46.59321],[12.19261,46.62059],[12.1818,46.6192],[12.17117,46.63275],[12.16062,46.63574],[12.1511,46.63215],[12.1436,46.6327],[12.13739,46.64122],[12.12342,46.64475],[12.10949,46.65204],[12.10609,46.65783],[12.09345,46.66123],[12.08826,46.66638],[12.07985,46.66686],[12.07038,46.67386],[12.07173,46.66064],[12.06686,46.65364],[12.07479,46.64329],[12.06837,46.63997],[12.06495,46.62121],[12.05448,46.61778],[12.05318,46.60989],[12.04613,46.60716],[12.05043,46.60016],[12.04763,46.58357],[12.03665,46.57668],[12.0266,46.55871],[12.02189,46.55791],[11.99941,46.53208],[11.99411,46.53345],[11.98704,46.54417],[11.96633,46.54363],[11.95094,46.53869],[11.94719,46.52879],[11.94147,46.52689],[11.93294,46.52631],[11.9121,46.532],[11.8904,46.52175],[11.85192,46.51682],[11.82849,46.50783],[11.82334,46.51315],[11.82391,46.52141],[11.81086,46.53146],[11.79385,46.52023],[11.79189,46.51322],[11.76157,46.50503],[11.74317,46.50391],[11.73202,46.50877],[11.71935,46.50916],[11.71524,46.51245],[11.69889,46.50218],[11.6672,46.49647],[11.64515,46.49743],[11.63849,46.50051],[11.63495,46.49486],[11.64297,46.49346],[11.65174,46.48271],[11.64536,46.47189],[11.64179,46.47439],[11.62679,46.4708],[11.62987,46.46377],[11.61882,46.44325],[11.62143,46.42539],[11.60161,46.39731],[11.60307,46.38924],[11.5932,46.38265],[11.56489,46.38018],[11.55878,46.35076],[11.55249,46.34418],[11.54423,46.34483],[11.53837,46.35015],[11.52445,46.35502],[11.47969,46.36277],[11.48052,46.3551],[11.46322,46.34922],[11.45556,46.33396],[11.42105,46.32441],[11.40517,46.32387],[11.39865,46.31426],[11.39994,46.30709],[11.39569,46.3083],[11.38188,46.30052],[11.36088,46.29906],[11.36078,46.29682],[11.38256,46.29177],[11.3871,46.28143],[11.39609,46.27423],[11.39862,46.264],[11.38756,46.26029],[11.37347,46.2629],[11.36836,46.26135],[11.35783,46.26481],[11.35495,46.27564],[11.33912,46.28306],[11.33379,46.29049],[11.33471,46.2962],[11.3129,46.28256],[11.31737,46.27303],[11.30645,46.25786],[11.29124,46.2604],[11.24743,46.22933],[11.20622,46.2187],[11.18267,46.22496],[11.17077,46.23806],[11.17994,46.24434],[11.18351,46.25269],[11.18935,46.25354],[11.19448,46.2461],[11.20029,46.25566],[11.16604,46.26129],[11.14885,46.27904],[11.13725,46.28336],[11.14293,46.28934],[11.15847,46.29059],[11.16439,46.2986],[11.1761,46.30346],[11.1847,46.32104],[11.18894,46.32151],[11.18696,46.32673],[11.1942,46.33016],[11.20204,46.34212],[11.19001,46.35984],[11.19263,46.36578],[11.20393,46.36765],[11.19792,46.37232],[11.21275,46.39804],[11.21345,46.40675],[11.20565,46.4166],[11.21026,46.4206],[11.20347,46.42682],[11.21416,46.43556],[11.21634,46.44255],[11.20903,46.45293],[11.21419,46.45807],[11.21736,46.45731],[11.21886,46.46199],[11.21626,46.47277],[11.20939,46.481],[11.20876,46.49346],[11.19608,46.50241],[11.1924,46.501],[11.18686,46.50734],[11.18002,46.49823],[11.17014,46.49635],[11.16095,46.4878],[11.12934,46.48058],[11.1103,46.49643],[11.10449,46.4948],[11.08812,46.50128],[11.08173,46.53021],[11.05915,46.51508],[11.03795,46.51357],[11.05006,46.50784],[11.05773,46.49235],[11.06278,46.4894],[11.06894,46.46619],[11.07625,46.45487],[11.0778,46.44569],[11.07301,46.44042],[11.05394,46.44849],[11.0414,46.44569],[11.02817,46.46116],[11.00952,46.46917],[11.00462,46.47607],[10.98695,46.48289],[10.96543,46.48103],[10.95791,46.46983],[10.93819,46.46578],[10.9325,46.45831],[10.93332,46.4528],[10.91305,46.44284],[10.89161,46.44366],[10.88324,46.44995],[10.88093,46.44579],[10.87162,46.4438],[10.86174,46.43509],[10.85113,46.43817],[10.80034,46.44185],[10.78906,46.45164],[10.77835,46.47112],[10.76934,46.47609],[10.76463,46.4848],[10.75906,46.48547],[10.74422,46.48333],[10.71753,46.46022],[10.69667,46.4573],[10.68293,46.44846],[10.66821,46.45122],[10.63303,46.44309],[10.61439,46.45098],[10.60128,46.46139],[10.59995,46.46766],[10.57672,46.47237],[10.55875,46.48187],[10.54986,46.49123],[10.53685,46.49062],[10.52657,46.49425],[10.49366,46.49719],[10.48141,46.49337],[10.45714,46.5096],[10.45124,46.53083],[10.45814,46.54215],[10.47056,46.54377],[10.46954,46.54856],[10.47617,46.55749],[10.47321,46.56701],[10.48305,46.5777],[10.48575,46.58921],[10.48221,46.59199],[10.48576,46.59805],[10.48291,46.60512],[10.49055,46.61394],[10.44632,46.63989],[10.40935,46.63389],[10.40011,46.63648],[10.39873,46.6455],[10.38946,46.65862],[10.39057,46.67089],[10.3803,46.68399],[10.38615,46.68821]]],"terms_url":"http://geoservices.buergernetz.bz.it/geokatalog/","terms_text":"© Autonomen Provinz Bozen/Provincia Autonoma di Bolzano CC-BY 3.0","id":"South-Tyrol-Orthofoto2011"},{"name":"South Tyrol Orthofoto 2014","type":"tms","description":"Orthophoto of South Tyrol from 2011","template":"http://geoservices.buergernetz.bz.it/geoserver/gwc/service/wmts/?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=P_BZ_OF_2014_EPSG3857&STYLE=default&TILEMATRIXSET=GoogleMapsCompatible&TILEMATRIX=GoogleMapsCompatible%3A{zoom}&TILEROW={y}&TILECOL={x}&FORMAT=image%2Fjpeg","scaleExtent":[0,18],"polygon":[[[12.23442,46.84254],[12.24913,46.82785],[12.24913,46.81945],[12.25753,46.81735],[12.26173,46.80686],[12.26594,46.80686],[12.26804,46.79637],[12.26173,46.79427],[12.27014,46.78587],[12.27224,46.76908],[12.28485,46.76698],[12.29745,46.7439],[12.30166,46.7439],[12.30166,46.7376],[12.28695,46.7376],[12.23652,46.72081],[12.18819,46.71451],[12.16298,46.70192],[12.10835,46.69353],[12.08944,46.68303],[12.05792,46.68093],[12.04531,46.67464],[12.03481,46.67464],[12.03061,46.68303],[12.0096,46.68303],[11.98438,46.66834],[11.94866,46.66414],[11.93816,46.65575],[11.90874,46.64525],[11.89193,46.64525],[11.8457,46.62846],[11.82049,46.62636],[11.80998,46.60748],[11.79528,46.60328],[11.78897,46.59069],[11.78057,46.58859],[11.76586,46.55501],[11.75325,46.54871],[11.73855,46.52982],[11.73224,46.52982],[11.72384,46.51513],[11.71543,46.51513],[11.71333,46.50254],[11.70913,46.50254],[11.70913,46.49624],[11.69652,46.48575],[11.69442,46.47735],[11.66711,46.47525],[11.66711,46.44587],[11.6608,46.44587],[11.64399,46.45846],[11.63769,46.45846],[11.63349,46.44587],[11.62508,46.44797],[11.62508,46.43957],[11.61878,46.43957],[11.61458,46.42278],[11.61037,46.42278],[11.61037,46.41649],[11.62508,46.41229],[11.62508,46.3934],[11.61458,46.38291],[11.60617,46.38291],[11.60407,46.37241],[11.58306,46.37241],[11.58306,46.34932],[11.55995,46.32414],[11.53894,46.32834],[11.53894,46.34513],[11.52423,46.34723],[11.50111,46.34723],[11.49901,46.32834],[11.48851,46.33044],[11.49271,46.32204],[11.41917,46.32414],[11.41707,46.25278],[11.35613,46.24858],[11.34773,46.25698],[11.34563,46.26747],[11.34143,46.26747],[11.33722,46.25068],[11.31201,46.24858],[11.30991,46.25278],[11.3015,46.25278],[11.2889,46.24019],[11.2889,46.2234],[11.25108,46.2234],[11.24898,46.2129],[11.16283,46.215],[11.16283,46.24858],[11.12711,46.24858],[11.13131,46.25278],[11.12291,46.25488],[11.12501,46.29895],[11.16283,46.29895],[11.16283,46.36821],[11.16703,46.36821],[11.16703,46.38081],[11.17543,46.3871],[11.17754,46.3997],[11.20485,46.3997],[11.20695,46.42068],[11.19014,46.42068],[11.19014,46.42698],[11.19435,46.42698],[11.19855,46.44167],[11.20485,46.44587],[11.20695,46.47315],[11.19014,46.47525],[11.18804,46.48365],[11.15232,46.47525],[11.08298,46.47525],[11.08088,46.43537],[11.04096,46.42068],[11.01154,46.42068],[10.99894,46.44587],[10.98843,46.44587],[10.98423,46.45217],[10.96952,46.45217],[10.96112,46.48365],[10.95691,46.48365],[10.95481,46.49414],[10.94851,46.49624],[10.94431,46.50673],[10.91069,46.49624],[10.90018,46.49624],[10.89808,46.51093],[10.85606,46.50254],[10.84135,46.54241],[10.86446,46.54661],[10.86236,46.55081],[10.76571,46.54031],[10.72158,46.55081],[10.59762,46.55291],[10.5619,46.54871],[10.53668,46.55291],[10.50096,46.54871],[10.48415,46.55501],[10.46314,46.55501],[10.47155,46.5676],[10.47365,46.59069],[10.47785,46.59069],[10.47785,46.61797],[10.46944,46.62636],[10.44843,46.63476],[10.42532,46.62846],[10.3938,46.63056],[10.3896,46.64525],[10.3812,46.64735],[10.3833,46.66414],[10.3791,46.66834],[10.3791,46.69353],[10.3854,46.72081],[10.3896,46.72081],[10.3938,46.7376],[10.41692,46.75229],[10.41692,46.78587],[10.42112,46.79847],[10.42532,46.79847],[10.42532,46.80686],[10.43373,46.81106],[10.43793,46.79007],[10.44423,46.78377],[10.44843,46.7439],[10.45264,46.7439],[10.45684,46.72711],[10.46104,46.72711],[10.46524,46.71032],[10.46944,46.71032],[10.47365,46.67254],[10.47995,46.67044],[10.48415,46.65575],[10.48836,46.65575],[10.48415,46.62846],[10.48836,46.62846],[10.48836,46.62217],[10.49886,46.62007],[10.52828,46.62427],[10.49886,46.63056],[10.49886,46.64525],[10.50516,46.64316],[10.49886,46.66204],[10.51777,46.65785],[10.58921,46.66204],[10.63123,46.65365],[10.79302,46.65575],[10.79723,46.65155],[10.88127,46.65155],[10.89178,46.65785],[10.9275,46.66414],[10.94431,46.67464],[10.98003,46.67464],[11.00104,46.68303],[11.02415,46.68303],[11.05147,46.69772],[11.12711,46.70822],[11.13971,46.71242],[11.14392,46.71871],[11.17543,46.72081],[11.19855,46.7334],[11.24898,46.7355],[11.25318,46.72291],[11.2952,46.72921],[11.30571,46.70822],[11.31831,46.70822],[11.33722,46.71871],[11.38555,46.72081],[11.43178,46.7376],[11.50952,46.7439],[11.54734,46.75649],[11.56835,46.75649],[11.58306,46.76698],[11.60617,46.76908],[11.61037,46.77538],[11.69862,46.79427],[11.71753,46.79427],[11.72174,46.79007],[11.73855,46.75859],[11.74905,46.75019],[11.76166,46.70192],[11.76586,46.70192],[11.78687,46.71661],[11.8331,46.72291],[11.86041,46.7376],[11.90874,46.7439],[11.92135,46.75229],[11.95286,46.75859],[11.95917,46.76488],[11.99489,46.77538],[12.00749,46.77538],[12.0096,46.77958],[12.03061,46.78168],[12.05792,46.79427],[12.09995,46.79847],[12.13566,46.81316],[12.15878,46.81316],[12.18609,46.82785],[12.21551,46.83205],[12.23442,46.84254]],[[11.97388,46.96637],[11.99489,46.96007],[11.99489,46.95587],[12.0096,46.95797],[12.0117,46.94748],[12.0159,46.94748],[12.0117,46.94118],[12.018,46.93908],[12.02851,46.92229],[12.00749,46.9118],[11.97388,46.9055],[11.95707,46.89501],[11.91714,46.88871],[11.85831,46.86982],[11.8394,46.86982],[11.80158,46.85303],[11.76166,46.84464],[11.74905,46.83415],[11.68181,46.81945],[11.67971,46.81526],[11.6545,46.81106],[11.64399,46.80476],[11.63769,46.80686],[11.63139,46.82155],[11.62508,46.82155],[11.62298,46.83205],[11.61037,46.84464],[11.61668,46.84884],[11.61458,46.85723],[11.61037,46.85723],[11.61668,46.86563],[11.64609,46.86563],[11.68602,46.88242],[11.69022,46.88871],[11.74905,46.89711],[11.75325,46.90341],[11.78057,46.9076],[11.80158,46.9202],[11.8457,46.92649],[11.87722,46.94118],[11.89613,46.94328],[11.92135,46.95797],[11.96757,46.96217],[11.97388,46.96637]]],"terms_url":"http://geoservices.buergernetz.bz.it/geokatalog/","terms_text":"© Autonomen Provinz Bozen/Provincia Autonoma di Bolzano CC-BY 3.0","id":"South-Tyrol-Orthofoto2014","best":true},{"name":"South Tyrol Topomap","type":"tms","description":"Topographical basemap of South Tyrol","template":"http://geoservices.buergernetz.bz.it/geoserver/gwc/service/wmts/?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=P_BZ_BASEMAP_TOPO&STYLE=default&TILEMATRIXSET=GoogleMapsCompatible&TILEMATRIX=GoogleMapsCompatible%3A{z}&TILEROW={y}&TILECOL={x}&FORMAT=image%2Fjpeg","scaleExtent":[0,20],"polygon":[[[10.38615,46.68821],[10.39201,46.69016],[10.40215,46.70624],[10.41274,46.70821],[10.41622,46.71479],[10.4168,46.71847],[10.39934,46.73435],[10.43464,46.75356],[10.44107,46.75413],[10.44011,46.77149],[10.42123,46.78861],[10.42845,46.79755],[10.43851,46.79869],[10.44925,46.80462],[10.45602,46.81635],[10.45438,46.82221],[10.4583,46.82478],[10.45513,46.83059],[10.45906,46.83548],[10.46483,46.83624],[10.46229,46.8413],[10.46987,46.84933],[10.46819,46.8553],[10.47838,46.86013],[10.48372,46.85543],[10.49628,46.85305],[10.49931,46.84857],[10.52124,46.84653],[10.5527,46.8511],[10.55795,46.84695],[10.55264,46.8408],[10.55536,46.84087],[10.58883,46.85125],[10.59502,46.85829],[10.60936,46.8597],[10.62441,46.86558],[10.64858,46.86655],[10.66787,46.87651],[10.67297,46.87138],[10.69112,46.86861],[10.69786,46.86339],[10.69508,46.85308],[10.70594,46.84786],[10.71763,46.84795],[10.72333,46.83892],[10.75621,46.83383],[10.76481,46.82409],[10.76387,46.81971],[10.75239,46.81387],[10.74506,46.80223],[10.7276,46.79709],[10.73122,46.78925],[10.75722,46.78624],[10.77744,46.79149],[10.78678,46.79735],[10.81439,46.77662],[10.82479,46.77472],[10.83129,46.78138],[10.84112,46.78282],[10.85354,46.77506],[10.86845,46.77313],[10.86993,46.7669],[10.88294,46.76393],[10.88962,46.76529],[10.8951,46.77092],[10.90527,46.76911],[10.92299,46.7764],[10.92821,46.77408],[10.94388,46.77648],[10.97522,46.77361],[10.97932,46.77014],[10.99475,46.76804],[11.01397,46.77317],[11.02328,46.76715],[11.0346,46.79428],[11.04234,46.801],[11.03792,46.80562],[11.05633,46.80928],[11.07279,46.82092],[11.08171,46.82252],[11.0762,46.83384],[11.06887,46.83793],[11.07303,46.84345],[11.06988,46.85348],[11.08742,46.87927],[11.09961,46.88922],[11.09538,46.89178],[11.09795,46.89844],[11.0946,46.91247],[11.10792,46.91706],[11.10804,46.92632],[11.11418,46.93234],[11.13851,46.92865],[11.16322,46.94091],[11.16642,46.94479],[11.16114,46.94979],[11.1637,46.96677],[11.17598,46.96367],[11.18658,46.97062],[11.19527,46.97152],[11.20418,46.96877],[11.20688,46.96403],[11.22047,46.97025],[11.24139,46.9708],[11.24865,46.97517],[11.25582,46.97535],[11.26272,46.98169],[11.27662,46.98168],[11.28762,46.98699],[11.30709,46.98525],[11.3205,46.99345],[11.33765,46.98606],[11.34516,46.99169],[11.35932,46.99154],[11.37697,46.98025],[11.38324,46.97168],[11.40465,46.96609],[11.43929,46.97601],[11.45134,46.99294],[11.46803,46.99582],[11.46859,47.003],[11.47831,47.01201],[11.50238,47.01073],[11.50313,47.00808],[11.51366,47.00595],[11.51679,47.00091],[11.53381,46.99233],[11.53846,46.98519],[11.55297,46.99149],[11.57663,46.99657],[11.58,47.00277],[11.58879,47.00641],[11.59901,47.00657],[11.60944,47.01207],[11.62697,47.01437],[11.63629,47.00383],[11.66542,46.99304],[11.6885,46.99658],[11.71226,46.99416],[11.72897,46.97322],[11.74698,46.97013],[11.76411,46.97412],[11.78106,46.99342],[11.81526,46.991],[11.83564,46.99417],[11.84396,47.0025],[11.85192,47.0014],[11.86722,47.01252],[11.87393,47.01136],[11.8794,47.01714],[11.89137,47.01728],[11.91627,47.03422],[11.9329,47.03864],[11.94688,47.03464],[11.95457,47.04374],[11.96773,47.04158],[11.97912,47.0511],[11.98587,47.04815],[11.99534,47.05064],[12.02037,47.04821],[12.02968,47.05127],[12.03353,47.0583],[12.04276,47.06228],[12.07543,47.0605],[12.08035,47.06951],[12.09308,47.07791],[12.10329,47.07931],[12.11867,47.07445],[12.13561,47.08171],[12.15125,47.08049],[12.15997,47.08267],[12.18589,47.09322],[12.2278,47.08302],[12.24228,47.06892],[12.23786,47.0644],[12.21821,47.05795],[12.2182,47.04483],[12.20552,47.02595],[12.18048,47.02414],[12.16423,47.01782],[12.14786,47.02357],[12.12723,47.01218],[12.12285,47.00662],[12.1322,46.99339],[12.12974,46.98593],[12.13977,46.982],[12.13808,46.96514],[12.13328,46.96292],[12.13882,46.95764],[12.15927,46.95133],[12.1702,46.93758],[12.15414,46.91654],[12.14675,46.91413],[12.16205,46.908],[12.16959,46.91121],[12.19154,46.90682],[12.20106,46.8965],[12.2022,46.88806],[12.21663,46.87517],[12.22147,46.88084],[12.23125,46.88146],[12.2345,46.88919],[12.24162,46.89192],[12.27486,46.88512],[12.27979,46.87921],[12.27736,46.87319],[12.29326,46.86566],[12.2912,46.85704],[12.29733,46.84455],[12.30833,46.84137],[12.30726,46.83271],[12.285,46.81503],[12.29383,46.8027],[12.28905,46.79948],[12.28889,46.79427],[12.28232,46.79153],[12.28539,46.7839],[12.30943,46.78603],[12.35837,46.77583],[12.37036,46.74163],[12.38475,46.71745],[12.40283,46.70811],[12.41103,46.70701],[12.41522,46.70163],[12.42862,46.6997],[12.42943,46.69567],[12.44268,46.68979],[12.47501,46.68756],[12.4795,46.67969],[12.43473,46.66714],[12.40648,46.64167],[12.38115,46.64183],[12.37944,46.63733],[12.3915,46.62765],[12.38577,46.62154],[12.35939,46.61829],[12.34465,46.62376],[12.34034,46.63022],[12.33578,46.62732],[12.3172,46.62876],[12.31785,46.62355],[12.30802,46.61811],[12.28413,46.61623],[12.26982,46.62003],[12.25931,46.62809],[12.24502,46.62326],[12.24198,46.61586],[12.21241,46.60918],[12.20444,46.59836],[12.19228,46.59321],[12.19261,46.62059],[12.1818,46.6192],[12.17117,46.63275],[12.16062,46.63574],[12.1511,46.63215],[12.1436,46.6327],[12.13739,46.64122],[12.12342,46.64475],[12.10949,46.65204],[12.10609,46.65783],[12.09345,46.66123],[12.08826,46.66638],[12.07985,46.66686],[12.07038,46.67386],[12.07173,46.66064],[12.06686,46.65364],[12.07479,46.64329],[12.06837,46.63997],[12.06495,46.62121],[12.05448,46.61778],[12.05318,46.60989],[12.04613,46.60716],[12.05043,46.60016],[12.04763,46.58357],[12.03665,46.57668],[12.0266,46.55871],[12.02189,46.55791],[11.99941,46.53208],[11.99411,46.53345],[11.98704,46.54417],[11.96633,46.54363],[11.95094,46.53869],[11.94719,46.52879],[11.94147,46.52689],[11.93294,46.52631],[11.9121,46.532],[11.8904,46.52175],[11.85192,46.51682],[11.82849,46.50783],[11.82334,46.51315],[11.82391,46.52141],[11.81086,46.53146],[11.79385,46.52023],[11.79189,46.51322],[11.76157,46.50503],[11.74317,46.50391],[11.73202,46.50877],[11.71935,46.50916],[11.71524,46.51245],[11.69889,46.50218],[11.6672,46.49647],[11.64515,46.49743],[11.63849,46.50051],[11.63495,46.49486],[11.64297,46.49346],[11.65174,46.48271],[11.64536,46.47189],[11.64179,46.47439],[11.62679,46.4708],[11.62987,46.46377],[11.61882,46.44325],[11.62143,46.42539],[11.60161,46.39731],[11.60307,46.38924],[11.5932,46.38265],[11.56489,46.38018],[11.55878,46.35076],[11.55249,46.34418],[11.54423,46.34483],[11.53837,46.35015],[11.52445,46.35502],[11.47969,46.36277],[11.48052,46.3551],[11.46322,46.34922],[11.45556,46.33396],[11.42105,46.32441],[11.40517,46.32387],[11.39865,46.31426],[11.39994,46.30709],[11.39569,46.3083],[11.38188,46.30052],[11.36088,46.29906],[11.36078,46.29682],[11.38256,46.29177],[11.3871,46.28143],[11.39609,46.27423],[11.39862,46.264],[11.38756,46.26029],[11.37347,46.2629],[11.36836,46.26135],[11.35783,46.26481],[11.35495,46.27564],[11.33912,46.28306],[11.33379,46.29049],[11.33471,46.2962],[11.3129,46.28256],[11.31737,46.27303],[11.30645,46.25786],[11.29124,46.2604],[11.24743,46.22933],[11.20622,46.2187],[11.18267,46.22496],[11.17077,46.23806],[11.17994,46.24434],[11.18351,46.25269],[11.18935,46.25354],[11.19448,46.2461],[11.20029,46.25566],[11.16604,46.26129],[11.14885,46.27904],[11.13725,46.28336],[11.14293,46.28934],[11.15847,46.29059],[11.16439,46.2986],[11.1761,46.30346],[11.1847,46.32104],[11.18894,46.32151],[11.18696,46.32673],[11.1942,46.33016],[11.20204,46.34212],[11.19001,46.35984],[11.19263,46.36578],[11.20393,46.36765],[11.19792,46.37232],[11.21275,46.39804],[11.21345,46.40675],[11.20565,46.4166],[11.21026,46.4206],[11.20347,46.42682],[11.21416,46.43556],[11.21634,46.44255],[11.20903,46.45293],[11.21419,46.45807],[11.21736,46.45731],[11.21886,46.46199],[11.21626,46.47277],[11.20939,46.481],[11.20876,46.49346],[11.19608,46.50241],[11.1924,46.501],[11.18686,46.50734],[11.18002,46.49823],[11.17014,46.49635],[11.16095,46.4878],[11.12934,46.48058],[11.1103,46.49643],[11.10449,46.4948],[11.08812,46.50128],[11.08173,46.53021],[11.05915,46.51508],[11.03795,46.51357],[11.05006,46.50784],[11.05773,46.49235],[11.06278,46.4894],[11.06894,46.46619],[11.07625,46.45487],[11.0778,46.44569],[11.07301,46.44042],[11.05394,46.44849],[11.0414,46.44569],[11.02817,46.46116],[11.00952,46.46917],[11.00462,46.47607],[10.98695,46.48289],[10.96543,46.48103],[10.95791,46.46983],[10.93819,46.46578],[10.9325,46.45831],[10.93332,46.4528],[10.91305,46.44284],[10.89161,46.44366],[10.88324,46.44995],[10.88093,46.44579],[10.87162,46.4438],[10.86174,46.43509],[10.85113,46.43817],[10.80034,46.44185],[10.78906,46.45164],[10.77835,46.47112],[10.76934,46.47609],[10.76463,46.4848],[10.75906,46.48547],[10.74422,46.48333],[10.71753,46.46022],[10.69667,46.4573],[10.68293,46.44846],[10.66821,46.45122],[10.63303,46.44309],[10.61439,46.45098],[10.60128,46.46139],[10.59995,46.46766],[10.57672,46.47237],[10.55875,46.48187],[10.54986,46.49123],[10.53685,46.49062],[10.52657,46.49425],[10.49366,46.49719],[10.48141,46.49337],[10.45714,46.5096],[10.45124,46.53083],[10.45814,46.54215],[10.47056,46.54377],[10.46954,46.54856],[10.47617,46.55749],[10.47321,46.56701],[10.48305,46.5777],[10.48575,46.58921],[10.48221,46.59199],[10.48576,46.59805],[10.48291,46.60512],[10.49055,46.61394],[10.44632,46.63989],[10.40935,46.63389],[10.40011,46.63648],[10.39873,46.6455],[10.38946,46.65862],[10.39057,46.67089],[10.3803,46.68399],[10.38615,46.68821]]],"terms_url":"http://geoservices.buergernetz.bz.it/geokatalog/","terms_text":"© Autonomen Provinz Bozen/Provincia Autonoma di Bolzano","id":"South-Tyrol-Topomap"},{"name":"Stadt Uster Orthophoto 2008 10cm","type":"tms","template":"http://mapproxy.sosm.ch:8080/tiles/uster/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","polygon":[[[8.6,47.31],[8.6,47.39],[8.77,47.39],[8.77,47.31],[8.6,47.31]]],"terms_text":"Stadt Uster Vermessung Orthophoto 2008"},{"name":"Stadt Zürich Luftbild 2011","type":"tms","template":"http://mapproxy.sosm.ch:8080/tiles/zh_luftbild2011/EPSG900913/{z}/{x}/{y}.png?origin=nw","polygon":[[[8.4441,47.3141],[8.4441,47.4411],[8.6284,47.4411],[8.6284,47.3141],[8.4441,47.3141]]],"terms_text":"Stadt Zürich Luftbild 2011"},{"name":"Stadtplan Zürich","type":"tms","template":"http://mapproxy.sosm.ch:8080/tiles/zh_stadtplan/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","polygon":[[[8.4482,47.321],[8.4482,47.4339],[8.6248,47.4339],[8.6248,47.321],[8.4482,47.321]]],"terms_text":"Stadt Zürich Open Government Data"},{"name":"Stamen Terrain","type":"tms","template":"http://{switch:a,b,c,d}.tile.stamen.com/terrain-background/{z}/{x}/{y}.jpg","scaleExtent":[4,18],"polygon":[[[-125.990173,48.9962416],[-125.989419,47.9948396],[-123.9929739,47.9955062],[-123.9922429,47.0059202],[-125.988688,47.0052409],[-125.9879604,46.0015618],[-123.9939396,46.0022529],[-123.9925238,43.9961708],[-124.9931832,43.9958116],[-124.9918175,41.9942149],[-125.9851789,41.9938465],[-125.9838655,40.0076111],[-123.9833285,40.0083757],[-123.9814115,37.002615],[-122.21903,37.0033173],[-122.2184144,36.011671],[-122.020087,36.011751],[-122.0188591,33.9961766],[-119.9787757,33.9970206],[-119.9775867,31.9987658],[-114.0122833,32.00129],[-114.0116894,30.9862401],[-105.998294,30.9896679],[-105.9971419,28.9901065],[-102.0210506,28.9918418],[-102.0204916,28.00733],[-100.0062436,28.0082173],[-100.0051143,25.991909],[-98.0109067,25.9928035],[-98.0103613,25.0063461],[-97.0161086,25.0067957],[-97.016654,25.9932494],[-95.9824825,25.9937132],[-95.9835999,27.9891175],[-94.0200898,27.9899826],[-94.0206586,28.9918129],[-88.0156706,28.9944338],[-88.0162494,30.0038862],[-86.0277506,30.0047454],[-86.0271719,28.9953016],[-84.0187909,28.9961781],[-84.017095,25.9817708],[-81.9971976,25.9826768],[-81.9966618,25.0134917],[-84.0165592,25.0125783],[-84.0160068,24.0052745],[-80.0199985,24.007096],[-80.0245309,32.0161282],[-78.0066484,32.0169819],[-78.0072238,32.9894278],[-77.8807233,32.9894807],[-77.8813253,33.9955918],[-76.0115411,33.9963653],[-76.0121459,34.9952552],[-74.0068449,34.9960749],[-74.0099997,40.0084254],[-72.0013745,40.0091931],[-72.002019,40.9912464],[-69.8797398,40.9920457],[-69.8804173,42.00893],[-69.9927682,42.0088883],[-69.9934462,43.0105166],[-67.9845366,43.0112496],[-67.985224,44.0103812],[-65.9892568,44.0110975],[-65.9921237,47.9993584],[-70.006442,47.9980181],[-70.005708,47.0042007],[-72.023686,47.003514],[-72.0222508,45.0059846],[-78.0146667,45.0038705],[-78.0139662,44.0026998],[-80.029686,44.0019763],[-80.0290052,43.0122994],[-81.995479,43.011582],[-81.9982986,47.0042713],[-87.505706,47.0023972],[-87.5064535,48.0142702],[-88.0260889,48.0140968],[-88.026838,49.0086686],[-93.9981078,49.0067142],[-93.9988778,50.0086456],[-96.0138899,50.0079995],[-96.0131199,49.0060547],[-125.990173,48.9962416]]],"terms_url":"http://maps.stamen.com/#terrain","terms_text":"Map tiles by Stamen Design, under CC BY 3.0"},{"name":"Stevns (Denmark)","type":"tms","template":"http://{switch:a,b,c}.tile.openstreetmap.dk/stevns/2009/{zoom}/{x}/{y}.png","scaleExtent":[0,20],"polygon":[[[12.0913942,55.3491574],[12.0943104,55.3842256],[12.1573875,55.3833103],[12.1587287,55.4013326],[12.1903468,55.400558],[12.1931411,55.4364665],[12.2564251,55.4347995],[12.2547073,55.4168882],[12.3822489,55.4134349],[12.3795942,55.3954143],[12.4109213,55.3946958],[12.409403,55.3766417],[12.4407807,55.375779],[12.4394142,55.3578314],[12.4707413,55.3569971],[12.4629475,55.2672214],[12.4315633,55.2681491],[12.430045,55.2502103],[12.3672011,55.2519673],[12.3656858,55.2340267],[12.2714604,55.2366031],[12.2744467,55.272476],[12.2115654,55.2741475],[12.2130078,55.2920322],[12.1815665,55.2928638],[12.183141,55.3107091],[12.2144897,55.3100981],[12.2159927,55.3279764],[12.1214458,55.3303379],[12.1229489,55.3483291],[12.0913942,55.3491574]]],"terms_text":"Stevns Kommune"},{"name":"Surrey Air Survey","type":"tms","template":"http://gravitystorm.dev.openstreetmap.org/surrey/{zoom}/{x}/{y}.png","scaleExtent":[8,19],"polygon":[[[-0.752478,51.0821941],[-0.7595183,51.0856254],[-0.8014342,51.1457917],[-0.8398864,51.1440686],[-0.8357665,51.1802397],[-0.8529549,51.2011266],[-0.8522683,51.2096231],[-0.8495217,51.217903],[-0.8266907,51.2403696],[-0.8120995,51.2469248],[-0.7736474,51.2459577],[-0.7544213,51.2381127],[-0.754078,51.233921],[-0.7446366,51.2333836],[-0.7430693,51.2847178],[-0.751503,51.3069524],[-0.7664376,51.3121032],[-0.7820588,51.3270157],[-0.7815438,51.3388135],[-0.7374268,51.3720456],[-0.7192307,51.3769748],[-0.6795769,51.3847961],[-0.6807786,51.3901523],[-0.6531411,51.3917591],[-0.6301385,51.3905808],[-0.6291085,51.3970074],[-0.6234437,51.3977572],[-0.613144,51.4295552],[-0.6002471,51.4459121],[-0.5867081,51.4445365],[-0.5762368,51.453202],[-0.5626755,51.4523462],[-0.547741,51.4469972],[-0.5372697,51.4448575],[-0.537098,51.4526671],[-0.5439644,51.4545926],[-0.5405312,51.4698865],[-0.5309182,51.4760881],[-0.5091172,51.4744843],[-0.5086022,51.4695657],[-0.4900628,51.4682825],[-0.4526406,51.4606894],[-0.4486924,51.4429316],[-0.4414826,51.4418616],[-0.4418259,51.4369394],[-0.4112702,51.4380095],[-0.4014855,51.4279498],[-0.3807145,51.4262372],[-0.3805428,51.4161749],[-0.3491288,51.4138195],[-0.3274994,51.4037544],[-0.3039818,51.3990424],[-0.3019219,51.3754747],[-0.309475,51.369688],[-0.3111916,51.3529669],[-0.2955704,51.3541462],[-0.2923089,51.3673303],[-0.2850991,51.3680805],[-0.2787476,51.3771891],[-0.2655297,51.3837247],[-0.2411538,51.3847961],[-0.2123147,51.3628288],[-0.2107697,51.3498578],[-0.190857,51.3502867],[-0.1542931,51.3338802],[-0.1496583,51.3057719],[-0.1074296,51.2966491],[-0.0887185,51.3099571],[-0.0878602,51.3220811],[-0.0652009,51.3215448],[-0.0641709,51.3264793],[-0.0519829,51.3263721],[-0.0528412,51.334631],[-0.0330779,51.3430876],[0.0019187,51.3376339],[0.0118751,51.3281956],[0.013935,51.2994398],[0.0202865,51.2994398],[0.0240631,51.3072743],[0.0331611,51.3086694],[0.0455207,51.30545],[0.0523872,51.2877392],[0.0616569,51.2577764],[0.0640602,51.2415518],[0.0462074,51.2126342],[0.0407142,51.2109136],[0.0448341,51.1989753],[0.0494689,51.1997283],[0.0558204,51.1944573],[0.0611419,51.1790713],[0.0623435,51.1542061],[0.0577087,51.1417146],[0.0204582,51.1365447],[-0.0446015,51.1336364],[-0.1566964,51.1352522],[-0.1572114,51.1290043],[-0.2287942,51.1183379],[-0.2473336,51.1183379],[-0.2500802,51.1211394],[-0.299347,51.1137042],[-0.3221779,51.1119799],[-0.3223496,51.1058367],[-0.3596001,51.1019563],[-0.3589135,51.1113333],[-0.3863793,51.1117644],[-0.3869014,51.1062516],[-0.4281001,51.0947174],[-0.4856784,51.0951554],[-0.487135,51.0872266],[-0.5297404,51.0865404],[-0.5302259,51.0789914],[-0.61046,51.076551],[-0.6099745,51.080669],[-0.6577994,51.0792202],[-0.6582849,51.0743394],[-0.6836539,51.0707547],[-0.6997979,51.070831],[-0.7296581,51.0744919],[-0.752478,51.0821941]]]},{"name":"Szeged ortophoto 2011","type":"tms","template":"http://e.tile.openstreetmap.hu/szeged-2011-10cm/{zoom}/{x}/{y}.png","scaleExtent":[10,22],"polygon":[[[20.1459914,46.2281144],[20.1332261,46.2290431],[20.1258373,46.2298686],[20.122329,46.2309893],[20.1208484,46.2317537],[20.1189709,46.2335126],[20.1131237,46.2413638],[20.1120293,46.2433005],[20.1115733,46.2449996],[20.1111871,46.247092],[20.1112944,46.2487725],[20.1115948,46.2509686],[20.1122171,46.2528047],[20.1129949,46.2542681],[20.1135421,46.2553549],[20.1147705,46.2567977],[20.1352251,46.2768529],[20.1366386,46.2775055],[20.1378939,46.2780301],[20.1393932,46.2783508],[20.1408818,46.2784583],[20.1611494,46.278159],[20.1621093,46.2781579],[20.1635894,46.277702],[20.1661777,46.2761484],[20.1687795,46.2738569],[20.1696108,46.2714413],[20.1695895,46.2704465],[20.1700871,46.2704418],[20.1739897,46.2643295],[20.1766182,46.2582878],[20.1947983,46.25492],[20.1858719,46.2448077],[20.1846595,46.2453122],[20.1780371,46.2383112],[20.1781766,46.2377101],[20.1795258,46.2370961],[20.1725666,46.2300241],[20.1698349,46.2350404],[20.1687701,46.2362946],[20.1670262,46.2378475],[20.1659431,46.2387342],[20.1654408,46.2389988],[20.1654837,46.2389988],[20.1635177,46.2401383],[20.1602051,46.2412003],[20.1592684,46.241531],[20.1592684,46.2415751],[20.1583504,46.2418505],[20.1549473,46.2422869],[20.1510796,46.2351538],[20.1493804,46.232459],[20.1459914,46.2281144]]],"terms_url":"http://www.geo.u-szeged.hu/","terms_text":"SZTE TFGT - University of Szeged"},{"name":"Thunderforest Landscape","type":"tms","template":"https://{switch:a,b,c}.tile.thunderforest.com/landscape/{zoom}/{x}/{y}.png","scaleExtent":[0,22],"terms_url":"http://www.thunderforest.com/terms/","terms_text":"Maps © Thunderforest, Data © OpenStreetMap contributors"},{"name":"Toulouse - Orthophotoplan 2007","type":"tms","template":"http://wms.openstreetmap.fr/tms/1.0.0/toulouse_ortho2007/{zoom}/{x}/{y}","scaleExtent":[0,22],"polygon":[[[1.1919978,43.6328791],[1.2015377,43.6329729],[1.2011107,43.6554932],[1.2227985,43.6557029],[1.2226231,43.6653353],[1.2275341,43.6653849],[1.2275417,43.6656387],[1.2337568,43.6656883],[1.2337644,43.6650153],[1.2351218,43.6650319],[1.2350913,43.6670729],[1.2443566,43.6671556],[1.2441584,43.6743925],[1.2493973,43.6744256],[1.2493973,43.6746628],[1.2555666,43.6747234],[1.2555742,43.6744532],[1.2569545,43.6744697],[1.2568782,43.678529],[1.2874873,43.6788257],[1.2870803,43.7013229],[1.3088219,43.7014632],[1.3086493,43.7127673],[1.3303262,43.7129544],[1.3300242,43.7305221],[1.3367106,43.7305845],[1.3367322,43.7312235],[1.3734338,43.7310456],[1.3735848,43.7245772],[1.4604504,43.7252947],[1.4607783,43.7028034],[1.4824875,43.7029516],[1.4829828,43.6692071],[1.5046832,43.6693616],[1.5048383,43.6581174],[1.5265475,43.6582656],[1.5266945,43.6470298],[1.548368,43.6471633],[1.5485357,43.6359385],[1.5702172,43.636082],[1.5705123,43.6135777],[1.5488166,43.6134276],[1.549097,43.5909479],[1.5707695,43.5910694],[1.5709373,43.5798341],[1.5793714,43.5798894],[1.5794782,43.5737682],[1.5809119,43.5737792],[1.5810859,43.5573794],[1.5712334,43.5573131],[1.5716504,43.5235497],[1.3984804,43.5222618],[1.3986509,43.5110113],[1.3120959,43.5102543],[1.3118968,43.5215192],[1.2902569,43.5213126],[1.2898637,43.5438168],[1.311517,43.5440133],[1.3113271,43.5552596],[1.3036924,43.5551924],[1.3036117,43.5595099],[1.2955449,43.5594317],[1.2955449,43.5595489],[1.2895595,43.5594473],[1.2892899,43.5775366],[1.2675698,43.5773647],[1.2673973,43.5886141],[1.25355,43.5885047],[1.2533774,43.5956282],[1.2518029,43.5956282],[1.2518029,43.5949409],[1.2350437,43.5947847],[1.2350437,43.5945972],[1.2239572,43.5945972],[1.2239357,43.5994708],[1.2139708,43.599299],[1.2138845,43.6046408],[1.2020647,43.6044846],[1.2019464,43.61048],[1.1924294,43.6103695],[1.1919978,43.6328791]]],"terms_url":"https://wiki.openstreetmap.org/wiki/Toulouse/ToulouseMetropoleData","terms_text":"ToulouseMetropole"},{"name":"Toulouse - Orthophotoplan 2011","type":"tms","template":"http://wms.openstreetmap.fr/tms/1.0.0/toulouse_ortho2011/{zoom}/{x}/{y}","scaleExtent":[0,22],"polygon":[[[1.1135067,43.6867566],[1.1351836,43.6870842],[1.1348907,43.6983471],[1.1782867,43.6990338],[1.1779903,43.7102786],[1.1996591,43.7106144],[1.1993387,43.7218722],[1.2427356,43.7225269],[1.2424336,43.7337491],[1.2641536,43.734092],[1.2638301,43.7453588],[1.2855285,43.7456548],[1.2852481,43.756935],[1.306925,43.757231],[1.3066446,43.7684779],[1.3283431,43.7687894],[1.3280842,43.780034],[1.4367275,43.7815757],[1.4373098,43.7591004],[1.4590083,43.7593653],[1.4593318,43.7481479],[1.4810303,43.7483972],[1.4813322,43.7371777],[1.5030307,43.7374115],[1.5035915,43.7149664],[1.5253115,43.7151846],[1.5256135,43.7040057],[1.5472688,43.7042552],[1.5475708,43.6930431],[1.5692045,43.6932926],[1.5695712,43.6820316],[1.5912049,43.6822656],[1.5917441,43.6597998],[1.613421,43.6600339],[1.613723,43.6488291],[1.6353783,43.6490788],[1.6384146,43.5140731],[1.2921649,43.5094658],[1.2918629,43.5206966],[1.2702076,43.5203994],[1.2698841,43.5316437],[1.2482288,43.531331],[1.2476048,43.5537788],[1.2259628,43.5534914],[1.2256819,43.564716],[1.2039835,43.564419],[1.2033148,43.5869049],[1.1816164,43.5865611],[1.1810237,43.6090368],[1.1592821,43.6086932],[1.1589585,43.6199523],[1.1372601,43.6196244],[1.1365933,43.642094],[1.1149055,43.6417629],[1.1135067,43.6867566]]],"terms_url":"https://wiki.openstreetmap.org/wiki/Toulouse/ToulouseMetropoleData","terms_text":"ToulouseMetropole"},{"name":"Toulouse - Orthophotoplan 2013","type":"tms","template":"http://wms.openstreetmap.fr/tms/1.0.0/toulouse_2013/{zoom}/{x}/{y}","scaleExtent":[0,22],"polygon":[[[1.1135067,43.6867566],[1.1351836,43.6870842],[1.1348907,43.6983471],[1.1782867,43.6990338],[1.1779903,43.7102786],[1.1996591,43.7106144],[1.1993387,43.7218722],[1.2427356,43.7225269],[1.2424336,43.7337491],[1.2641536,43.734092],[1.2638301,43.7453588],[1.2855285,43.7456548],[1.2852481,43.756935],[1.306925,43.757231],[1.3066446,43.7684779],[1.3283431,43.7687894],[1.3280842,43.780034],[1.4367275,43.7815757],[1.4373098,43.7591004],[1.4590083,43.7593653],[1.4593318,43.7481479],[1.4810303,43.7483972],[1.4813322,43.7371777],[1.5030307,43.7374115],[1.5035915,43.7149664],[1.5253115,43.7151846],[1.5256135,43.7040057],[1.5472688,43.7042552],[1.5475708,43.6930431],[1.5692045,43.6932926],[1.5695712,43.6820316],[1.5912049,43.6822656],[1.5917441,43.6597998],[1.613421,43.6600339],[1.613723,43.6488291],[1.6353783,43.6490788],[1.6384146,43.5140731],[1.2921649,43.5094658],[1.2918629,43.5206966],[1.2702076,43.5203994],[1.2698841,43.5316437],[1.2482288,43.531331],[1.2476048,43.5537788],[1.2259628,43.5534914],[1.2256819,43.564716],[1.2039835,43.564419],[1.2033148,43.5869049],[1.1816164,43.5865611],[1.1810237,43.6090368],[1.1592821,43.6086932],[1.1589585,43.6199523],[1.1372601,43.6196244],[1.1365933,43.642094],[1.1149055,43.6417629],[1.1135067,43.6867566]]],"terms_url":"https://wiki.openstreetmap.org/wiki/Toulouse/ToulouseMetropoleData","terms_text":"ToulouseMetropole"},{"name":"Toulouse - Orthophotoplan 2015","type":"tms","template":"http://wms.openstreetmap.fr/tms/1.0.0/toulouse_2015/{zoom}/{x}/{y}","scaleExtent":[0,22],"polygon":[[[1.1135067,43.6867566],[1.1351836,43.6870842],[1.1348907,43.6983471],[1.1782867,43.6990338],[1.1779903,43.7102786],[1.1996591,43.7106144],[1.1993387,43.7218722],[1.2427356,43.7225269],[1.2424336,43.7337491],[1.2641536,43.734092],[1.2638301,43.7453588],[1.2855285,43.7456548],[1.2852481,43.756935],[1.306925,43.757231],[1.3066446,43.7684779],[1.3283431,43.7687894],[1.3280842,43.780034],[1.4367275,43.7815757],[1.4373098,43.7591004],[1.4590083,43.7593653],[1.4593318,43.7481479],[1.4810303,43.7483972],[1.4813322,43.7371777],[1.5030307,43.7374115],[1.5035915,43.7149664],[1.5253115,43.7151846],[1.5256135,43.7040057],[1.5472688,43.7042552],[1.5475708,43.6930431],[1.5692045,43.6932926],[1.5695712,43.6820316],[1.5912049,43.6822656],[1.5917441,43.6597998],[1.613421,43.6600339],[1.613723,43.6488291],[1.6353783,43.6490788],[1.6384146,43.5140731],[1.2921649,43.5094658],[1.2918629,43.5206966],[1.2702076,43.5203994],[1.2698841,43.5316437],[1.2482288,43.531331],[1.2476048,43.5537788],[1.2259628,43.5534914],[1.2256819,43.564716],[1.2039835,43.564419],[1.2033148,43.5869049],[1.1816164,43.5865611],[1.1810237,43.6090368],[1.1592821,43.6086932],[1.1589585,43.6199523],[1.1372601,43.6196244],[1.1365933,43.642094],[1.1149055,43.6417629],[1.1135067,43.6867566]]],"terms_url":"https://wiki.openstreetmap.org/wiki/Toulouse/ToulouseMetropoleData","terms_text":"ToulouseMetropole"},{"name":"Tours - Orthophotos 2008-2010","type":"tms","template":"http://wms.openstreetmap.fr/tms/1.0.0/tours/{zoom}/{x}/{y}","scaleExtent":[0,20],"polygon":[[[0.5457462,47.465264],[0.54585,47.4608163],[0.5392188,47.4606983],[0.5393484,47.456243],[0.5327959,47.4561003],[0.5329011,47.451565],[0.52619,47.4514013],[0.5265854,47.4424884],[0.5000941,47.4420739],[0.5002357,47.4375835],[0.4936014,47.4374324],[0.4937,47.4329285],[0.4606141,47.4324593],[0.4607248,47.4279827],[0.4541016,47.4278125],[0.454932,47.4053921],[0.4615431,47.4054476],[0.4619097,47.3964924],[0.4684346,47.3966005],[0.4691319,47.3786415],[0.4757125,47.3787609],[0.4762116,47.3652018],[0.4828297,47.3653499],[0.4829611,47.3608321],[0.4763543,47.360743],[0.476654,47.3517263],[0.4700497,47.3516186],[0.4701971,47.3471313],[0.4637503,47.3470104],[0.4571425,47.3424146],[0.4572922,47.3379061],[0.4506741,47.3378081],[0.4508379,47.3333051],[0.4442212,47.3332032],[0.4443809,47.328711],[0.4311392,47.3284977],[0.4316262,47.3150004],[0.4382432,47.3151136],[0.4383815,47.3106174],[0.4714487,47.3111374],[0.4713096,47.3156565],[0.477888,47.3157542],[0.4780733,47.3112802],[0.4846826,47.3113639],[0.4848576,47.3068686],[0.4914359,47.3069803],[0.491745,47.2979733],[0.4851578,47.2978722],[0.4854269,47.2888744],[0.4788485,47.2887697],[0.4791574,47.2797818],[0.4857769,47.2799005],[0.4859107,47.2753885],[0.492539,47.2755029],[0.4926669,47.2710127],[0.4992986,47.2711066],[0.4994296,47.2666116],[0.5192658,47.2669245],[0.5194225,47.2624231],[0.5260186,47.2625205],[0.5258735,47.2670183],[0.5456972,47.2673383],[0.5455537,47.2718283],[0.5587737,47.2720366],[0.5586259,47.2765185],[0.5652252,47.2766278],[0.5650848,47.2811206],[0.5716753,47.2812285],[0.5715223,47.2857217],[0.5781436,47.2858299],[0.5779914,47.2903294],[0.5846023,47.2904263],[0.5843076,47.2994231],[0.597499,47.2996094],[0.5976637,47.2951375],[0.6571596,47.2960036],[0.6572988,47.2915091],[0.6705019,47.2917186],[0.6703475,47.2962082],[0.6836175,47.2963688],[0.6834322,47.3008929],[0.690062,47.3009558],[0.6899241,47.3054703],[0.7362019,47.3061157],[0.7360848,47.3106063],[0.7559022,47.3108935],[0.7557718,47.315392],[0.7623755,47.3154716],[0.7622314,47.3199941],[0.7754911,47.3201546],[0.77497,47.3388218],[0.7745786,47.351628],[0.7680363,47.3515901],[0.767589,47.3605298],[0.7742443,47.3606238],[0.7733465,47.3921266],[0.7667434,47.3920195],[0.7664411,47.4010837],[0.7730647,47.4011115],[0.7728868,47.4101297],[0.7661849,47.4100226],[0.7660267,47.4145044],[0.7527613,47.4143038],[0.7529788,47.4098086],[0.7462373,47.4097016],[0.7459424,47.4232208],[0.7392324,47.4231451],[0.738869,47.4366116],[0.7323267,47.4365171],[0.7321869,47.4410556],[0.7255048,47.44098],[0.7254209,47.4453479],[0.7318793,47.4454803],[0.7318514,47.4501126],[0.7384496,47.450226],[0.7383098,47.454631],[0.7449359,47.4547444],[0.7443209,47.4771985],[0.7310685,47.4769717],[0.7309008,47.4815445],[0.7176205,47.4812611],[0.7177883,47.4768394],[0.69777,47.4764993],[0.6980496,47.4719827],[0.6914514,47.4718882],[0.6917309,47.4630241],[0.6851048,47.4629295],[0.684937,47.4673524],[0.678255,47.4673335],[0.6779754,47.4762158],[0.6714051,47.4761592],[0.6710417,47.4881952],[0.6577334,47.4879685],[0.6578173,47.48504],[0.6511911,47.4848322],[0.6514707,47.4758568],[0.6448166,47.4757245],[0.6449284,47.4712646],[0.6117976,47.4707543],[0.6118815,47.4663129],[0.6052833,47.4661239],[0.6054231,47.4616631],[0.5988808,47.4615497],[0.5990206,47.4570886],[0.572488,47.4566916],[0.5721805,47.4656513],[0.5457462,47.465264]]],"terms_url":"http://wiki.openstreetmap.org/wiki/Tours/Orthophoto","terms_text":"Orthophoto Tour(s) Plus 2008"},{"name":"Tours - Orthophotos 2013","type":"tms","template":"http://wms.openstreetmap.fr/tms/1.0.0/tours_2013/{zoom}/{x}/{y}","scaleExtent":[0,22],"polygon":[[[0.427093505859375,47.26199018174824],[0.427093505859375,47.50096732311069],[0.814361572265625,47.50096732311069],[0.814361572265625,47.26199018174824],[0.427093505859375,47.26199018174824]]],"terms_url":"http://wiki.openstreetmap.org/wiki/Tours/Orthophoto","terms_text":"Orthophoto Tour(s)plus 2013"},{"name":"U.S. Forest Service roads","type":"tms","template":"http://osm.cycle.travel/forest/{zoom}/{x}/{y}.png","scaleExtent":[0,19],"polygon":[[[-124.7617886,48.4130148],[-124.6059492,45.90245],[-124.9934269,40.0557614],[-122.5369737,36.8566086],[-119.9775867,33.0064099],[-117.675935,32.4630223],[-114.8612307,32.4799891],[-111.0089311,31.336015],[-108.1992687,31.3260016],[-108.1871123,31.7755116],[-106.5307225,31.7820947],[-106.4842052,31.7464455],[-106.429317,31.7520583],[-106.2868855,31.5613291],[-106.205248,31.446704],[-105.0205259,30.5360988],[-104.5881916,29.6997856],[-103.2518856,28.8908685],[-102.7173632,29.3920567],[-102.1513983,29.7475702],[-101.2552871,29.4810523],[-100.0062436,28.0082173],[-99.2351068,26.4475962],[-98.0109067,25.9928035],[-97.435024,25.8266009],[-96.9555259,25.9821589],[-96.8061741,27.7978168],[-95.5563349,28.5876066],[-93.7405308,29.4742093],[-90.9028456,28.8564513],[-88.0156706,28.9944338],[-88.0162494,30.0038862],[-86.0277506,30.0047454],[-84.0187909,28.9961781],[-81.9971976,25.9826768],[-81.9966618,25.0134917],[-84.0165592,25.0125783],[-84.0160068,24.0052745],[-80.0199985,24.007096],[-79.8901116,26.8550713],[-80.0245309,32.0161282],[-75.4147385,35.0531894],[-74.0211163,39.5727927],[-72.002019,40.9912464],[-69.8797398,40.9920457],[-69.8489304,43.2619916],[-66.9452845,44.7104937],[-67.7596632,47.0990024],[-69.2505131,47.5122328],[-70.4614886,46.2176574],[-71.412273,45.254878],[-72.0222508,45.0059846],[-75.0798841,44.9802854],[-76.9023061,43.8024568],[-78.7623935,43.6249578],[-79.15798,43.4462589],[-79.0060087,42.8005317],[-82.662475,41.6889458],[-82.1761642,43.588535],[-83.2813977,46.138853],[-87.5064535,48.0142702],[-88.3492194,48.2963271],[-89.4353148,47.9837822],[-93.9981078,49.0067142],[-95.1105379,49.412004],[-96.0131199,49.0060547],[-123.3228926,49.0042878],[-123.2275233,48.1849927],[-124.7617886,48.4130148]],[[-160.5787616,22.5062947],[-160.5782192,21.4984647],[-158.7470604,21.2439843],[-157.5083185,20.995803],[-155.9961942,18.7790194],[-154.6217803,18.7586966],[-154.6890176,19.8805722],[-156.2927622,21.2225888],[-157.5047384,21.9984962],[-159.0093692,22.5070181],[-160.5787616,22.5062947]],[[-167.1571546,68.721974],[-164.8553982,67.0255078],[-168.002195,66.0017503],[-169.0087448,66.001546],[-169.0075381,64.9987675],[-172.5143281,63.8767267],[-173.8197023,59.74014],[-162.5018149,58.0005815],[-160.0159024,58.0012389],[-160.0149725,57.000035],[-160.5054788,56.9999017],[-165.8092575,54.824847],[-178.000097,52.2446469],[-177.9992996,51.2554252],[-171.4689067,51.8215329],[-162.40251,53.956664],[-159.0075717,55.002502],[-158.0190709,55.0027849],[-151.9963213,55.9991902],[-151.500341,57.9987853],[-151.5012894,58.9919816],[-138.5159989,58.9953194],[-138.5150471,57.9986434],[-133.9948193,54.0031685],[-130.0044418,54.0043387],[-130.0070826,57.0000507],[-131.975877,56.9995156],[-135.1229873,59.756601],[-138.0071813,59.991805],[-139.1715881,60.4127229],[-140.9874011,61.0118551],[-140.9683975,69.9535069],[-156.176891,71.5633329],[-160.413634,70.7397728],[-163.0218273,69.9707435],[-164.9717003,68.994689],[-167.1571546,68.721974]]]},{"name":"Übersichtsplan Zürich","type":"tms","template":"http://mapproxy.sosm.ch:8080/tiles/zh_uebersichtsplan/EPSG900913/{zoom}/{x}/{y}.png?origin=nw","scaleExtent":[0,21],"polygon":[[[8.4482,47.321],[8.4482,47.4339],[8.6248,47.4339],[8.6248,47.321],[8.4482,47.321]]],"terms_text":"Stadt Zürich Open Government Data"},{"name":"USGS Large Scale Imagery","type":"tms","template":"http://{switch:a,b,c}.tile.openstreetmap.us/usgs_large_scale/{zoom}/{x}/{y}.jpg","scaleExtent":[12,20],"polygon":[[[-123.2549305,48.7529029],[-123.2549305,48.5592263],[-123.192224,48.5592263],[-123.192224,48.4348366],[-122.9419646,48.4348366],[-122.9419646,48.3720812],[-122.8806229,48.3720812],[-122.8806229,48.3094763],[-122.8167566,48.3094763],[-122.8167566,48.1904587],[-123.0041133,48.1904587],[-123.0041133,48.1275918],[-123.058416,48.1275918],[-123.058416,48.190514],[-123.254113,48.190514],[-123.254113,48.1274982],[-123.3706593,48.1274982],[-123.3706593,48.1908403],[-124.0582632,48.1908403],[-124.0582632,48.253442],[-124.1815163,48.253442],[-124.1815163,48.3164666],[-124.4319117,48.3164666],[-124.4319117,48.3782613],[-124.5564618,48.3782613],[-124.5564618,48.4408305],[-124.7555107,48.4408305],[-124.7555107,48.1914986],[-124.8185282,48.1914986],[-124.8185282,48.1228381],[-124.7552951,48.1228381],[-124.7552951,47.5535253],[-124.3812108,47.5535253],[-124.3812108,47.1218696],[-124.1928897,47.1218696],[-124.1928897,43.7569431],[-124.4443382,43.7569431],[-124.4443382,43.1425556],[-124.6398855,43.1425556],[-124.6398855,42.6194503],[-124.4438525,42.6194503],[-124.4438525,39.8080662],[-123.8815685,39.8080662],[-123.8815685,39.1102825],[-123.75805,39.1102825],[-123.75805,38.4968799],[-123.2702803,38.4968799],[-123.2702803,37.9331905],[-122.8148084,37.9331905],[-122.8148084,37.8019606],[-122.5664316,37.8019606],[-122.5664316,36.9319611],[-121.8784026,36.9319611],[-121.8784026,36.6897596],[-122.0034748,36.6897596],[-122.0034748,36.4341056],[-121.9414159,36.4341056],[-121.9414159,35.9297636],[-121.5040977,35.9297636],[-121.5040977,35.8100273],[-121.3790276,35.8100273],[-121.3790276,35.4239164],[-120.9426515,35.4239164],[-120.9426515,35.1849683],[-120.8171978,35.1849683],[-120.8171978,35.1219894],[-120.6918447,35.1219894],[-120.6918447,34.4966794],[-120.5045898,34.4966794],[-120.5045898,34.4339651],[-120.0078775,34.4339651],[-120.0078775,34.3682626],[-119.5283517,34.3682626],[-119.5283517,34.0576434],[-119.0060985,34.0576434],[-119.0060985,33.9975267],[-118.5046259,33.9975267],[-118.5046259,33.8694631],[-118.4413209,33.8694631],[-118.4413209,33.6865253],[-118.066912,33.6865253],[-118.066912,33.3063832],[-117.5030045,33.3063832],[-117.5030045,33.0500337],[-117.3188195,33.0500337],[-117.3188195,32.6205888],[-117.1917023,32.6205888],[-117.1917023,32.4974566],[-116.746496,32.4974566],[-116.746496,32.5609161],[-115.9970138,32.5609161],[-115.9970138,32.6264942],[-114.8808125,32.6264942],[-114.8808125,32.4340796],[-114.6294474,32.4340796],[-114.6294474,32.3731636],[-114.4447437,32.3731636],[-114.4447437,32.3075418],[-114.2557628,32.3075418],[-114.2557628,32.2444561],[-114.0680274,32.2444561],[-114.0680274,32.1829113],[-113.8166499,32.1829113],[-113.8166499,32.1207622],[-113.6307421,32.1207622],[-113.6307421,32.0565099],[-113.4417495,32.0565099],[-113.4417495,31.9984372],[-113.2546027,31.9984372],[-113.2546027,31.9325434],[-113.068072,31.9325434],[-113.068072,31.8718062],[-112.8161105,31.8718062],[-112.8161105,31.8104171],[-112.6308756,31.8104171],[-112.6308756,31.7464723],[-112.4418918,31.7464723],[-112.4418918,31.6856001],[-112.257192,31.6856001],[-112.257192,31.6210352],[-112.0033787,31.6210352],[-112.0033787,31.559584],[-111.815619,31.559584],[-111.815619,31.4970238],[-111.6278586,31.4970238],[-111.6278586,31.4339867],[-111.4418978,31.4339867],[-111.4418978,31.3733859],[-111.2559708,31.3733859],[-111.2559708,31.3113225],[-108.1845822,31.3113225],[-108.1845822,31.7459502],[-106.5065055,31.7459502],[-106.5065055,31.6842308],[-106.3797265,31.6842308],[-106.3797265,31.621752],[-106.317434,31.621752],[-106.317434,31.4968167],[-106.2551769,31.4968167],[-106.2551769,31.4344889],[-106.1924698,31.4344889],[-106.1924698,31.3721296],[-106.0039212,31.3721296],[-106.0039212,31.309328],[-105.9416582,31.309328],[-105.9416582,31.2457547],[-105.8798174,31.2457547],[-105.8798174,31.1836194],[-105.8162349,31.1836194],[-105.8162349,31.1207155],[-105.6921198,31.1207155],[-105.6921198,31.0584835],[-105.6302881,31.0584835],[-105.6302881,30.9328271],[-105.5044418,30.9328271],[-105.5044418,30.8715864],[-105.4412973,30.8715864],[-105.4412973,30.808463],[-105.3781497,30.808463],[-105.3781497,30.7471828],[-105.1904658,30.7471828],[-105.1904658,30.6843231],[-105.1286244,30.6843231],[-105.1286244,30.6199737],[-105.0036504,30.6199737],[-105.0036504,30.5589058],[-104.9417962,30.5589058],[-104.9417962,30.4963236],[-104.8782018,30.4963236],[-104.8782018,30.3098261],[-104.8155257,30.3098261],[-104.8155257,30.2478305],[-104.7536079,30.2478305],[-104.7536079,29.9353916],[-104.690949,29.9353916],[-104.690949,29.8090156],[-104.6291301,29.8090156],[-104.6291301,29.6843577],[-104.5659869,29.6843577],[-104.5659869,29.6223459],[-104.5037188,29.6223459],[-104.5037188,29.5595436],[-104.4410072,29.5595436],[-104.4410072,29.4974832],[-104.2537551,29.4974832],[-104.2537551,29.3716718],[-104.1291984,29.3716718],[-104.1291984,29.3091621],[-104.0688737,29.3091621],[-104.0688737,29.2467276],[-103.8187309,29.2467276],[-103.8187309,29.1843076],[-103.755736,29.1843076],[-103.755736,29.1223174],[-103.5667542,29.1223174],[-103.5667542,29.0598119],[-103.5049819,29.0598119],[-103.5049819,28.9967506],[-103.3165753,28.9967506],[-103.3165753,28.9346923],[-103.0597572,28.9346923],[-103.0597572,29.0592965],[-102.9979694,29.0592965],[-102.9979694,29.1212855],[-102.9331397,29.1212855],[-102.9331397,29.1848575],[-102.8095989,29.1848575],[-102.8095989,29.2526154],[-102.8701345,29.2526154],[-102.8701345,29.308096],[-102.8096681,29.308096],[-102.8096681,29.3715484],[-102.7475655,29.3715484],[-102.7475655,29.5581899],[-102.684554,29.5581899],[-102.684554,29.6847655],[-102.4967764,29.6847655],[-102.4967764,29.7457694],[-102.3086647,29.7457694],[-102.3086647,29.8086627],[-102.1909323,29.8086627],[-102.1909323,29.7460097],[-101.5049914,29.7460097],[-101.5049914,29.6846777],[-101.3805796,29.6846777],[-101.3805796,29.5594459],[-101.3175057,29.5594459],[-101.3175057,29.4958934],[-101.1910075,29.4958934],[-101.1910075,29.4326115],[-101.067501,29.4326115],[-101.067501,29.308808],[-100.9418897,29.308808],[-100.9418897,29.2456231],[-100.8167271,29.2456231],[-100.8167271,29.1190449],[-100.7522672,29.1190449],[-100.7522672,29.0578214],[-100.6925358,29.0578214],[-100.6925358,28.8720431],[-100.6290158,28.8720431],[-100.6290158,28.8095363],[-100.5679901,28.8095363],[-100.5679901,28.622554],[-100.5040411,28.622554],[-100.5040411,28.5583804],[-100.4421832,28.5583804],[-100.4421832,28.4968266],[-100.379434,28.4968266],[-100.379434,28.3092865],[-100.3171942,28.3092865],[-100.3171942,28.1835681],[-100.254483,28.1835681],[-100.254483,28.1213885],[-100.1282282,28.1213885],[-100.1282282,28.059215],[-100.0659537,28.059215],[-100.0659537,27.9966087],[-100.0023855,27.9966087],[-100.0023855,27.9332152],[-99.9426497,27.9332152],[-99.9426497,27.7454658],[-99.816851,27.7454658],[-99.816851,27.6834301],[-99.7541346,27.6834301],[-99.7541346,27.6221543],[-99.6291629,27.6221543],[-99.6291629,27.5588977],[-99.5672838,27.5588977],[-99.5672838,27.4353752],[-99.5041798,27.4353752],[-99.5041798,27.3774021],[-99.5671796,27.3774021],[-99.5671796,27.2463726],[-99.504975,27.2463726],[-99.504975,26.9965649],[-99.4427427,26.9965649],[-99.4427427,26.872803],[-99.3800633,26.872803],[-99.3800633,26.8068179],[-99.3190684,26.8068179],[-99.3190684,26.7473614],[-99.2537541,26.7473614],[-99.2537541,26.6210068],[-99.1910617,26.6210068],[-99.1910617,26.4956737],[-99.1300639,26.4956737],[-99.1300639,26.3713808],[-99.0029473,26.3713808],[-99.0029473,26.3093836],[-98.816572,26.3093836],[-98.816572,26.2457762],[-98.6920082,26.2457762],[-98.6920082,26.1837096],[-98.4440896,26.1837096],[-98.4440896,26.1217217],[-98.3823181,26.1217217],[-98.3823181,26.0596488],[-98.2532707,26.0596488],[-98.2532707,25.9986871],[-98.0109084,25.9986871],[-98.0109084,25.9932255],[-97.6932319,25.9932255],[-97.6932319,25.9334103],[-97.6313904,25.9334103],[-97.6313904,25.8695893],[-97.5046779,25.8695893],[-97.5046779,25.8073488],[-97.3083401,25.8073488],[-97.3083401,25.8731159],[-97.2456326,25.8731159],[-97.2456326,25.9353731],[-97.1138939,25.9353731],[-97.1138939,27.6809179],[-97.0571035,27.6809179],[-97.0571035,27.8108242],[-95.5810766,27.8108242],[-95.5810766,28.7468827],[-94.271041,28.7468827],[-94.271041,29.5594076],[-92.5029947,29.5594076],[-92.5029947,29.4974754],[-91.8776216,29.4974754],[-91.8776216,29.3727013],[-91.378418,29.3727013],[-91.378418,29.2468326],[-91.3153953,29.2468326],[-91.3153953,29.1844301],[-91.1294702,29.1844301],[-91.1294702,29.1232559],[-91.0052632,29.1232559],[-91.0052632,28.9968437],[-89.4500159,28.9968437],[-89.4500159,28.8677422],[-88.8104309,28.8677422],[-88.8104309,30.1841864],[-85.8791527,30.1841864],[-85.8791527,29.5455038],[-84.8368083,29.5455038],[-84.8368083,29.6225158],[-84.7482786,29.6225158],[-84.7482786,29.683624],[-84.685894,29.683624],[-84.685894,29.7468386],[-83.6296975,29.7468386],[-83.6296975,29.4324361],[-83.3174937,29.4324361],[-83.3174937,29.0579442],[-82.879659,29.0579442],[-82.879659,27.7453529],[-82.8182822,27.7453529],[-82.8182822,26.9290868],[-82.3796782,26.9290868],[-82.3796782,26.3694183],[-81.8777106,26.3694183],[-81.8777106,25.805971],[-81.5036862,25.805971],[-81.5036862,25.7474753],[-81.4405462,25.7474753],[-81.4405462,25.6851489],[-81.3155883,25.6851489],[-81.3155883,25.5600985],[-81.2538534,25.5600985],[-81.2538534,25.4342361],[-81.1902012,25.4342361],[-81.1902012,25.1234341],[-81.1288133,25.1234341],[-81.1288133,25.0619389],[-81.0649231,25.0619389],[-81.0649231,24.8157807],[-81.6289469,24.8157807],[-81.6289469,24.7538367],[-81.6907173,24.7538367],[-81.6907173,24.6899374],[-81.8173189,24.6899374],[-81.8173189,24.6279161],[-82.1910041,24.6279161],[-82.1910041,24.496294],[-81.6216596,24.496294],[-81.6216596,24.559484],[-81.372006,24.559484],[-81.372006,24.6220687],[-81.0593278,24.6220687],[-81.0593278,24.684826],[-80.9347147,24.684826],[-80.9347147,24.7474828],[-80.7471081,24.7474828],[-80.7471081,24.8100618],[-80.3629898,24.8100618],[-80.3629898,25.1175858],[-80.122344,25.1175858],[-80.122344,25.7472357],[-80.0588458,25.7472357],[-80.0588458,26.3708251],[-79.995837,26.3708251],[-79.995837,26.9398003],[-80.0587265,26.9398003],[-80.0587265,27.1277466],[-80.1226251,27.1277466],[-80.1226251,27.2534279],[-80.1846956,27.2534279],[-80.1846956,27.3781229],[-80.246175,27.3781229],[-80.246175,27.5658729],[-80.3094768,27.5658729],[-80.3094768,27.7530311],[-80.3721485,27.7530311],[-80.3721485,27.8774451],[-80.4351457,27.8774451],[-80.4351457,28.0033366],[-80.4966078,28.0033366],[-80.4966078,28.1277326],[-80.5587159,28.1277326],[-80.5587159,28.3723509],[-80.4966335,28.3723509],[-80.4966335,29.5160326],[-81.1213644,29.5160326],[-81.1213644,31.6846966],[-80.6018723,31.6846966],[-80.6018723,32.2475309],[-79.4921024,32.2475309],[-79.4921024,32.9970261],[-79.1116488,32.9970261],[-79.1116488,33.3729457],[-78.6153621,33.3729457],[-78.6153621,33.8097638],[-77.9316963,33.8097638],[-77.9316963,33.8718243],[-77.8692252,33.8718243],[-77.8692252,34.0552454],[-77.6826392,34.0552454],[-77.6826392,34.2974598],[-77.2453509,34.2974598],[-77.2453509,34.5598585],[-76.4973277,34.5598585],[-76.4973277,34.622796],[-76.4337602,34.622796],[-76.4337602,34.6849285],[-76.373212,34.6849285],[-76.373212,34.7467674],[-76.3059364,34.7467674],[-76.3059364,34.808551],[-76.2468017,34.808551],[-76.2468017,34.8728418],[-76.1825922,34.8728418],[-76.1825922,34.9335332],[-76.120814,34.9335332],[-76.120814,34.9952359],[-75.9979015,34.9952359],[-75.9979015,35.0578182],[-75.870338,35.0578182],[-75.870338,35.1219097],[-75.7462194,35.1219097],[-75.7462194,35.1818911],[-75.4929694,35.1818911],[-75.4929694,35.3082988],[-75.4325662,35.3082988],[-75.4325662,35.7542495],[-75.4969907,35.7542495],[-75.4969907,37.8105602],[-75.3082972,37.8105602],[-75.3082972,37.8720088],[-75.245601,37.8720088],[-75.245601,37.9954849],[-75.1828751,37.9954849],[-75.1828751,38.0585079],[-75.1184793,38.0585079],[-75.1184793,38.2469091],[-75.0592098,38.2469091],[-75.0592098,38.3704316],[-74.9948111,38.3704316],[-74.9948111,38.8718417],[-74.4878252,38.8718417],[-74.4878252,39.3089428],[-74.1766317,39.3089428],[-74.1766317,39.6224653],[-74.0567045,39.6224653],[-74.0567045,39.933178],[-73.9959035,39.933178],[-73.9959035,40.1854852],[-73.9341593,40.1854852],[-73.9341593,40.4959486],[-73.8723024,40.4959486],[-73.8723024,40.5527135],[-71.8074506,40.5527135],[-71.8074506,41.3088005],[-70.882512,41.3088005],[-70.882512,41.184978],[-70.7461947,41.184978],[-70.7461947,41.3091865],[-70.4337553,41.3091865],[-70.4337553,41.4963885],[-69.9334281,41.4963885],[-69.9334281,41.6230802],[-69.869857,41.6230802],[-69.869857,41.8776895],[-69.935791,41.8776895],[-69.935791,42.0032342],[-69.9975823,42.0032342],[-69.9975823,42.0650191],[-70.0606103,42.0650191],[-70.0606103,42.1294348],[-70.5572884,42.1294348],[-70.5572884,43.2487079],[-70.4974097,43.2487079],[-70.4974097,43.3092194],[-70.3704249,43.3092194],[-70.3704249,43.371963],[-70.3085701,43.371963],[-70.3085701,43.4969879],[-70.183921,43.4969879],[-70.183921,43.6223531],[-70.057583,43.6223531],[-70.057583,43.6850173],[-69.7455247,43.6850173],[-69.7455247,43.7476571],[-69.2472845,43.7476571],[-69.2472845,43.8107035],[-69.0560701,43.8107035],[-69.0560701,43.8717247],[-68.9950522,43.8717247],[-68.9950522,43.9982022],[-68.4963672,43.9982022],[-68.4963672,44.0597368],[-68.3081038,44.0597368],[-68.3081038,44.122137],[-68.1851802,44.122137],[-68.1851802,44.3081382],[-67.9956019,44.3081382],[-67.9956019,44.3727489],[-67.8103041,44.3727489],[-67.8103041,44.435178],[-67.4965289,44.435178],[-67.4965289,44.4968776],[-67.37102,44.4968776],[-67.37102,44.5600642],[-67.1848753,44.5600642],[-67.1848753,44.6213345],[-67.1221208,44.6213345],[-67.1221208,44.6867918],[-67.059365,44.6867918],[-67.059365,44.7473657],[-66.9311098,44.7473657],[-66.9311098,44.9406566],[-66.994683,44.9406566],[-66.994683,45.0024514],[-67.0595847,45.0024514],[-67.0595847,45.1273377],[-67.1201974,45.1273377],[-67.1201974,45.1910115],[-67.2469811,45.1910115],[-67.2469811,45.253442],[-67.3177546,45.253442],[-67.3177546,45.1898369],[-67.370749,45.1898369],[-67.370749,45.2534001],[-67.4326888,45.2534001],[-67.4326888,45.3083409],[-67.3708571,45.3083409],[-67.3708571,45.4396986],[-67.4305573,45.4396986],[-67.4305573,45.4950095],[-67.37099,45.4950095],[-67.37099,45.6264543],[-67.6214982,45.6264543],[-67.6214982,45.6896133],[-67.683828,45.6896133],[-67.683828,45.753259],[-67.7462097,45.753259],[-67.7462097,47.1268165],[-67.8700141,47.1268165],[-67.8700141,47.1900278],[-67.9323803,47.1900278],[-67.9323803,47.2539678],[-67.9959387,47.2539678],[-67.9959387,47.3149737],[-68.1206676,47.3149737],[-68.1206676,47.3780823],[-68.4423175,47.3780823],[-68.4423175,47.3166082],[-68.6314305,47.3166082],[-68.6314305,47.2544676],[-68.9978037,47.2544676],[-68.9978037,47.439895],[-69.0607223,47.439895],[-69.0607223,47.5047558],[-69.2538122,47.5047558],[-69.2538122,47.4398084],[-69.3179284,47.4398084],[-69.3179284,47.378601],[-69.4438546,47.378601],[-69.4438546,47.3156274],[-69.5038204,47.3156274],[-69.5038204,47.2525839],[-69.5667838,47.2525839],[-69.5667838,47.1910884],[-69.6303478,47.1910884],[-69.6303478,47.128701],[-69.6933103,47.128701],[-69.6933103,47.0654307],[-69.7557063,47.0654307],[-69.7557063,47.0042751],[-69.8180391,47.0042751],[-69.8180391,46.9415344],[-69.8804023,46.9415344],[-69.8804023,46.8792519],[-69.9421674,46.8792519],[-69.9421674,46.8177399],[-70.0063088,46.8177399],[-70.0063088,46.6920295],[-70.0704265,46.6920295],[-70.0704265,46.4425926],[-70.1945902,46.4425926],[-70.1945902,46.3785887],[-70.2562047,46.3785887],[-70.2562047,46.3152628],[-70.3203651,46.3152628],[-70.3203651,46.0651209],[-70.3814988,46.0651209],[-70.3814988,45.93552],[-70.3201618,45.93552],[-70.3201618,45.879479],[-70.4493131,45.879479],[-70.4493131,45.7538713],[-70.5070021,45.7538713],[-70.5070021,45.6916912],[-70.6316642,45.6916912],[-70.6316642,45.6291619],[-70.7575538,45.6291619],[-70.7575538,45.4414685],[-70.8809878,45.4414685],[-70.8809878,45.3780612],[-71.13328,45.3780612],[-71.13328,45.3151452],[-71.3830282,45.3151452],[-71.3830282,45.253416],[-71.5076448,45.253416],[-71.5076448,45.0655726],[-73.9418929,45.0655726],[-73.9418929,45.0031242],[-74.7469725,45.0031242],[-74.7469725,45.0649003],[-74.8800964,45.0649003],[-74.8800964,45.0029023],[-75.0662455,45.0029023],[-75.0662455,44.9415167],[-75.2539363,44.9415167],[-75.2539363,44.8776043],[-75.3789648,44.8776043],[-75.3789648,44.8153462],[-75.4431283,44.8153462],[-75.4431283,44.7536053],[-75.5666566,44.7536053],[-75.5666566,44.6909879],[-75.6290205,44.6909879],[-75.6290205,44.6284958],[-75.7540484,44.6284958],[-75.7540484,44.566385],[-75.817312,44.566385],[-75.817312,44.5028932],[-75.8799549,44.5028932],[-75.8799549,44.3784946],[-76.1300319,44.3784946],[-76.1300319,44.3159227],[-76.1926961,44.3159227],[-76.1926961,44.2534378],[-76.3182619,44.2534378],[-76.3182619,44.1916726],[-76.3792975,44.1916726],[-76.3792975,44.0653733],[-76.4427584,44.0653733],[-76.4427584,43.9963825],[-76.317027,43.9963825],[-76.317027,43.9414581],[-76.5076611,43.9414581],[-76.5076611,43.8723335],[-76.3829974,43.8723335],[-76.3829974,43.8091872],[-76.2534102,43.8091872],[-76.2534102,43.5665222],[-76.5064833,43.5665222],[-76.5064833,43.5033881],[-76.6331208,43.5033881],[-76.6331208,43.4432252],[-76.6951085,43.4432252],[-76.6951085,43.3786858],[-76.8177798,43.3786858],[-76.8177798,43.318066],[-77.682,43.318066],[-77.682,43.3789376],[-78.0565883,43.3789376],[-78.0565883,43.4396918],[-78.4389748,43.4396918],[-78.4389748,43.3794382],[-78.8803396,43.3794382],[-78.8803396,43.3149724],[-79.1298858,43.3149724],[-79.1298858,43.2429286],[-79.0669615,43.2429286],[-79.0669615,43.1299931],[-79.1298858,43.1299931],[-79.1298858,43.0577305],[-79.071264,43.0577305],[-79.071264,42.9294906],[-78.943264,42.9294906],[-78.943264,42.7542165],[-79.069439,42.7542165],[-79.069439,42.6941622],[-79.133439,42.6941622],[-79.133439,42.6296973],[-79.1947499,42.6296973],[-79.1947499,42.5663538],[-79.3786827,42.5663538],[-79.3786827,42.5033425],[-79.4442961,42.5033425],[-79.4442961,42.4410614],[-79.5679936,42.4410614],[-79.5679936,42.3775264],[-79.6906154,42.3775264],[-79.6906154,42.3171086],[-79.8164642,42.3171086],[-79.8164642,42.2534481],[-80.0052373,42.2534481],[-80.0052373,42.1909188],[-80.1916829,42.1909188],[-80.1916829,42.1272555],[-80.3167992,42.1272555],[-80.3167992,42.0669857],[-80.5063234,42.0669857],[-80.5063234,42.0034331],[-80.6930471,42.0034331],[-80.6930471,41.9415141],[-80.9440403,41.9415141],[-80.9440403,41.8781193],[-81.1942729,41.8781193],[-81.1942729,41.8166455],[-81.3190089,41.8166455],[-81.3190089,41.7545453],[-81.4418435,41.7545453],[-81.4418435,41.690965],[-81.5053523,41.690965],[-81.5053523,41.6301643],[-82.7470081,41.6301643],[-82.7470081,41.7536942],[-82.8839135,41.7536942],[-82.8839135,41.5656075],[-82.9957195,41.5656075],[-82.9957195,41.6270375],[-83.1257796,41.6270375],[-83.1257796,41.6878411],[-83.2474733,41.6878411],[-83.2474733,41.7536942],[-83.3737305,41.7536942],[-83.3737305,41.809276],[-83.3106019,41.809276],[-83.3106019,41.8716064],[-83.2474733,41.8716064],[-83.2474733,41.9361393],[-83.1843447,41.9361393],[-83.1843447,41.9960851],[-83.1207681,41.9960851],[-83.1207681,42.2464812],[-83.0589194,42.2464812],[-83.0589194,42.3089555],[-82.8685328,42.3089555],[-82.8685328,42.3717652],[-82.8072219,42.3717652],[-82.8072219,42.558553],[-82.7553745,42.558553],[-82.7553745,42.4954945],[-82.5599041,42.4954945],[-82.5599041,42.558553],[-82.4967755,42.558553],[-82.4967755,42.6833607],[-82.4328863,42.6833607],[-82.4328863,42.9342196],[-82.3700552,42.9342196],[-82.3700552,43.0648071],[-82.4328863,43.0648071],[-82.4328863,43.1917566],[-82.4947464,43.1917566],[-82.4947464,43.5034627],[-82.557133,43.5034627],[-82.557133,43.8160901],[-82.6197884,43.8160901],[-82.6197884,43.9422098],[-82.6839499,43.9422098],[-82.6839499,44.0022641],[-82.7465346,44.0022641],[-82.7465346,44.0670545],[-82.8708696,44.0670545],[-82.8708696,44.1291935],[-83.008517,44.1291935],[-83.008517,44.0664786],[-83.1336086,44.0664786],[-83.1336086,44.0053949],[-83.2414522,44.0053949],[-83.2414522,44.9962034],[-83.1806112,44.9962034],[-83.1806112,45.067302],[-83.2455172,45.067302],[-83.2455172,45.1287382],[-83.3065878,45.1287382],[-83.3065878,45.2551509],[-83.3706087,45.2551509],[-83.3706087,45.3165923],[-83.4325644,45.3165923],[-83.4325644,45.3792105],[-83.6178415,45.3792105],[-83.6178415,45.4419665],[-83.8084291,45.4419665],[-83.8084291,45.5036189],[-84.0550718,45.5036189],[-84.0550718,45.5647907],[-84.1235181,45.5647907],[-84.1235181,45.6287845],[-84.1807534,45.6287845],[-84.1807534,45.6914688],[-84.3111554,45.6914688],[-84.3111554,45.9337076],[-83.8209974,45.9337076],[-83.8209974,45.8725113],[-83.4968086,45.8725113],[-83.4968086,45.9337076],[-83.4338066,45.9337076],[-83.4338066,46.0016863],[-83.4962697,46.0016863],[-83.4962697,46.0668178],[-83.5599956,46.0668178],[-83.5599956,46.1261576],[-83.9954558,46.1261576],[-83.9954558,46.1931747],[-84.0591816,46.1931747],[-84.0591816,46.3814972],[-84.1152614,46.3814972],[-84.1152614,46.4953584],[-84.0591816,46.4953584],[-84.0591816,46.5682653],[-84.2579545,46.5682653],[-84.2579545,46.5051232],[-84.3071879,46.5051232],[-84.3071879,46.5682653],[-84.4415364,46.5682653],[-84.4415364,46.504525],[-84.9965729,46.504525],[-84.9965729,46.6842882],[-84.9298158,46.6842882],[-84.9298158,46.818077],[-85.3165894,46.818077],[-85.3165894,46.7535825],[-87.5562645,46.7535825],[-87.5562645,47.4407371],[-87.6825361,47.4407371],[-87.6825361,47.5035554],[-88.2560738,47.5035554],[-88.2560738,47.4433716],[-88.4417419,47.4433716],[-88.4417419,47.3789949],[-88.50683,47.3789949],[-88.50683,47.3153881],[-88.6312821,47.3153881],[-88.6312821,47.2539782],[-88.7569636,47.2539782],[-88.7569636,47.1934682],[-88.8838253,47.1934682],[-88.8838253,47.1284735],[-88.9434208,47.1284735],[-88.9434208,47.0662127],[-89.0708726,47.0662127],[-89.0708726,47.0026826],[-89.2565553,47.0026826],[-89.2565553,46.9410806],[-90.3677669,46.9410806],[-90.3677669,47.6844827],[-90.3069978,47.6844827],[-90.3069978,47.7460174],[-89.994859,47.7460174],[-89.994859,47.8082719],[-89.8048615,47.8082719],[-89.8048615,47.8700562],[-89.6797699,47.8700562],[-89.6797699,47.9339637],[-89.4933757,47.9339637],[-89.4933757,47.9957956],[-89.4284697,47.9957956],[-89.4284697,48.0656377],[-89.9932739,48.0656377],[-89.9932739,48.1282966],[-90.7455933,48.1282966],[-90.7455933,48.1893056],[-90.8087291,48.1893056],[-90.8087291,48.2522065],[-91.067763,48.2522065],[-91.067763,48.1916658],[-91.1946247,48.1916658],[-91.1946247,48.1279027],[-91.6814196,48.1279027],[-91.6814196,48.2525994],[-91.9321927,48.2525994],[-91.9321927,48.3142454],[-91.9929683,48.3142454],[-91.9929683,48.3780845],[-92.3189383,48.3780845],[-92.3189383,48.2529081],[-92.3732233,48.2529081],[-92.3732233,48.3153385],[-92.4322288,48.3153385],[-92.4322288,48.4411448],[-92.4977248,48.4411448],[-92.4977248,48.501781],[-92.5679413,48.501781],[-92.5679413,48.439579],[-92.6210462,48.439579],[-92.6210462,48.5650783],[-92.8086835,48.5650783],[-92.8086835,48.6286865],[-92.8086835,48.6267365],[-92.933185,48.6267365],[-92.933185,48.6922145],[-93.0051716,48.6922145],[-93.0051716,48.6282965],[-93.1225924,48.6282965],[-93.1225924,48.6922145],[-93.3190806,48.6922145],[-93.3190806,48.6267365],[-93.5049477,48.6267365],[-93.5049477,48.5635164],[-93.7474601,48.5635164],[-93.7474601,48.6267365],[-93.8135461,48.6267365],[-93.8135461,48.6898775],[-94.2453121,48.6898775],[-94.2453121,48.7554327],[-94.6183171,48.7554327],[-94.6183171,48.941036],[-94.6809018,48.941036],[-94.6809018,49.0029737],[-94.7441532,49.0029737],[-94.7441532,49.2536079],[-94.8084069,49.2536079],[-94.8084069,49.3784134],[-95.1192391,49.3784134],[-95.1192391,49.4425264],[-95.1934341,49.4425264],[-95.1934341,49.0035292],[-96.87069,49.0035292],[-96.87069,49.0656063],[-99.0049312,49.0656063],[-99.0049312,49.0050714],[-109.3699257,49.0050714],[-109.3699257,49.0668231],[-109.5058746,49.0668231],[-109.5058746,49.0050714],[-114.1830014,49.0050714],[-114.1830014,49.0687317],[-114.7578709,49.0687317],[-114.7578709,49.0050714],[-115.433731,49.0050714],[-115.433731,49.0671412],[-116.5062706,49.0671412],[-116.5062706,49.0050714],[-117.3089504,49.0050714],[-117.3089504,49.0659803],[-119.882945,49.0659803],[-119.882945,49.0050714],[-120.1208555,49.0050714],[-120.1208555,49.0678367],[-121.4451636,49.0678367],[-121.4451636,49.0050714],[-121.9311808,49.0050714],[-121.9311808,49.0656099],[-122.817484,49.0656099],[-122.817484,49.0029143],[-122.8795155,49.0029143],[-122.8795155,48.9347018],[-122.8174629,48.9347018],[-122.8174629,48.8101998],[-122.7538859,48.8101998],[-122.7538859,48.7533758],[-122.8712937,48.7533758],[-122.8712937,48.8153948],[-123.0055391,48.8153948],[-123.0055391,48.7529529],[-123.1296926,48.7529529],[-123.1296926,48.6902201],[-123.1838197,48.6902201],[-123.1838197,48.7529029],[-123.2549305,48.7529029]],[[-122.9341743,37.7521547],[-122.9347457,37.6842013],[-123.0679013,37.6849023],[-123.0673747,37.7475251],[-123.1292603,37.7478506],[-123.1286894,37.815685],[-123.0590687,37.8153192],[-123.0595947,37.7528143],[-122.9341743,37.7521547]],[[-71.6299464,41.2540893],[-71.4966465,41.2541393],[-71.4965596,41.122965],[-71.6298594,41.1229149],[-71.6299464,41.2540893]],[[-70.3184265,41.3775196],[-70.3183384,41.2448243],[-70.1906612,41.2448722],[-70.1906239,41.1886019],[-69.9336025,41.1886984],[-69.933729,41.3791941],[-69.9950664,41.3791712],[-69.995109,41.443159],[-70.0707828,41.4431307],[-70.0706972,41.3144915],[-70.2461667,41.3144258],[-70.2462087,41.3775467],[-70.3184265,41.3775196]],[[-68.9403374,43.9404062],[-68.6856948,43.9404977],[-68.6856475,43.8721797],[-68.7465405,43.8721577],[-68.7464976,43.8102529],[-68.8090782,43.8102304],[-68.8090343,43.746728],[-68.8773094,43.7467034],[-68.8773544,43.8117826],[-68.9402483,43.8117599],[-68.9403374,43.9404062]],[[-123.1291466,49.0645144],[-122.9954224,49.0645144],[-122.9954224,48.9343243],[-123.1291466,48.9343243],[-123.1291466,49.0645144]],[[-82.9407144,24.7535913],[-82.8719398,24.7535913],[-82.8719398,24.6905653],[-82.7446233,24.6905653],[-82.7446233,24.6214593],[-82.8088038,24.6214593],[-82.8088038,24.5594908],[-82.9407144,24.5594908],[-82.9407144,24.7535913]]]},{"name":"USGS Topographic Maps","type":"tms","template":"http://{switch:a,b,c}.tile.openstreetmap.us/usgs_scanned_topos/{zoom}/{x}/{y}.png","polygon":[[[-125.990173,48.9962416],[-125.989419,47.9948396],[-123.9929739,47.9955062],[-123.9922429,47.0059202],[-125.988688,47.0052409],[-125.9879604,46.0015618],[-123.9939396,46.0022529],[-123.9925238,43.9961708],[-124.9931832,43.9958116],[-124.9918175,41.9942149],[-125.9851789,41.9938465],[-125.9838655,40.0076111],[-123.9833285,40.0083757],[-123.9814115,37.002615],[-122.21903,37.0033173],[-122.2184144,36.011671],[-122.020087,36.011751],[-122.0188591,33.9961766],[-119.9787757,33.9970206],[-119.9775867,31.9987658],[-114.0122833,32.00129],[-114.0116894,30.9862401],[-105.998294,30.9896679],[-105.9971419,28.9901065],[-102.0210506,28.9918418],[-102.0204916,28.00733],[-100.0062436,28.0082173],[-100.0051143,25.991909],[-98.0109067,25.9928035],[-98.0103613,25.0063461],[-97.0161086,25.0067957],[-97.016654,25.9932494],[-95.9824825,25.9937132],[-95.9835999,27.9891175],[-94.0200898,27.9899826],[-94.0206586,28.9918129],[-88.0156706,28.9944338],[-88.0162494,30.0038862],[-86.0277506,30.0047454],[-86.0271719,28.9953016],[-84.0187909,28.9961781],[-84.017095,25.9817708],[-81.9971976,25.9826768],[-81.9966618,25.0134917],[-84.0165592,25.0125783],[-84.0160068,24.0052745],[-80.0199985,24.007096],[-80.0245309,32.0161282],[-78.0066484,32.0169819],[-78.0072238,32.9894278],[-77.8807233,32.9894807],[-77.8813253,33.9955918],[-76.0115411,33.9963653],[-76.0121459,34.9952552],[-74.0068449,34.9960749],[-74.0099997,40.0084254],[-72.0013745,40.0091931],[-72.002019,40.9912464],[-69.8797398,40.9920457],[-69.8804173,42.00893],[-69.9927682,42.0088883],[-69.9934462,43.0105166],[-67.9845366,43.0112496],[-67.985224,44.0103812],[-65.9892568,44.0110975],[-65.9921237,47.9993584],[-70.006442,47.9980181],[-70.005708,47.0042007],[-72.023686,47.003514],[-72.0222508,45.0059846],[-78.0146667,45.0038705],[-78.0139662,44.0026998],[-80.029686,44.0019763],[-80.0290052,43.0122994],[-81.995479,43.011582],[-81.9982986,47.0042713],[-87.505706,47.0023972],[-87.5064535,48.0142702],[-88.0260889,48.0140968],[-88.026838,49.0086686],[-93.9981078,49.0067142],[-93.9988778,50.0086456],[-96.0138899,50.0079995],[-96.0131199,49.0060547],[-125.990173,48.9962416]],[[-160.5787616,22.5062947],[-160.5782192,21.4984647],[-159.0030121,21.499196],[-159.0027422,20.9951068],[-157.5083185,20.995803],[-157.5080519,20.4960241],[-155.966889,20.4967444],[-155.9674267,21.5028287],[-157.5044717,21.5021151],[-157.5047384,21.9984962],[-159.0090946,21.9978002],[-159.0093692,22.5070181],[-160.5787616,22.5062947]],[[-168.006102,68.9941463],[-168.0047628,68.0107853],[-165.4842481,68.0112562],[-165.4829337,67.0037303],[-168.0034485,67.0032389],[-168.002195,66.0017503],[-169.0087448,66.001546],[-169.0075381,64.9987675],[-168.0009882,64.9989798],[-167.9998282,63.9982374],[-164.9871288,63.9988964],[-164.9860062,62.9950845],[-167.9987057,62.9944019],[-167.9946035,59.0153692],[-162.5027857,59.0167799],[-162.5018149,58.0005815],[-160.0159024,58.0012389],[-160.0149725,57.000035],[-160.5054788,56.9999017],[-160.5045719,55.9968161],[-164.012195,55.9958373],[-164.0113186,55.00107],[-165.994782,55.0005023],[-165.9941266,54.2400584],[-168.0002944,54.2394734],[-168.0000986,54.0094921],[-170.0156134,54.0089011],[-170.0147683,53.0016446],[-171.9993636,53.0010487],[-171.9989488,52.4977745],[-176.0083239,52.4965566],[-176.0081186,52.2452555],[-178.000097,52.2446469],[-177.9992996,51.2554252],[-176.0073212,51.2560472],[-176.0075146,51.4980163],[-171.9981395,51.4992617],[-171.9985419,51.9985373],[-167.9984317,51.9997661],[-167.9994645,53.2560877],[-165.9932968,53.2566866],[-165.9939308,54.0100804],[-159.0067205,54.0121291],[-159.0075717,55.002502],[-158.0190709,55.0027849],[-158.0199473,55.9975094],[-151.9963213,55.9991902],[-151.9981536,57.9986536],[-151.500341,57.9987853],[-151.5012894,58.9919816],[-138.5159989,58.9953194],[-138.5150471,57.9986434],[-136.6872422,57.9991267],[-136.6863158,57.0016688],[-135.9973698,57.001856],[-135.9964667,56.0030544],[-134.6717732,56.003424],[-134.6708865,54.9969623],[-133.9956734,54.9971556],[-133.9948193,54.0031685],[-130.0044418,54.0043387],[-130.0070826,57.0000507],[-131.975877,56.9995156],[-131.9787378,59.9933094],[-138.0071813,59.991805],[-138.0082158,61.0125755],[-140.9874011,61.0118551],[-140.99984,71.0039309],[-154.5023956,71.0017377],[-154.5039632,71.9983391],[-157.499048,71.9978773],[-157.4974758,70.9982877],[-163.0233611,70.9973899],[-163.0218273,69.9707435],[-164.9730896,69.97041],[-164.9717003,68.994689],[-168.006102,68.9941463]],[[-168.5133204,62.8689586],[-168.5144423,63.8765677],[-172.0202755,63.8757975],[-172.0191536,62.8681608],[-168.5133204,62.8689586]],[[-170.9947111,59.9954089],[-170.995726,60.9969787],[-174.0045311,60.9962508],[-174.0035162,59.9946581],[-170.9947111,59.9954089]],[[-156.0717261,20.2854602],[-154.7940471,20.2860582],[-154.7933145,18.9029464],[-156.0709936,18.9023432],[-156.0717261,20.2854602]]]},{"name":"Vector Streetmap for San Juan County WA","type":"tms","description":"Public domain street and address data from the San Juan County, WA. Updated at least quarterly.","template":"http://sjcgis.org/arcgis/rest/services/Basemaps/General_Basemap_WM/MapServer/tile/{zoom}/{y}/{x}","scaleExtent":[0,19],"polygon":[[[-123.274024,48.692975],[-123.007726,48.767256],[-123.007619,48.831577],[-122.783495,48.758416],[-122.693402,48.658522],[-122.767451,48.603606],[-122.744842,48.387083],[-123.248221,48.283531],[-123.114524,48.422614],[-123.219035,48.548575],[-123.274024,48.692975]]],"best":true},{"name":"Vejmidte (Denmark)","type":"tms","template":"http://{switch:a,b,c}.tile.openstreetmap.dk/danmark/vejmidte/{zoom}/{x}/{y}.png","scaleExtent":[0,20],"polygon":[[[8.3743941,54.9551655],[8.3683809,55.4042149],[8.2103997,55.4039795],[8.2087314,55.4937345],[8.0502655,55.4924731],[8.0185123,56.7501399],[8.1819161,56.7509948],[8.1763274,57.0208898],[8.3413329,57.0219872],[8.3392467,57.1119574],[8.5054433,57.1123212],[8.5033923,57.2020499],[9.3316304,57.2027636],[9.3319079,57.2924835],[9.4978864,57.2919578],[9.4988593,57.3820608],[9.6649749,57.3811615],[9.6687295,57.5605591],[9.8351961,57.5596265],[9.8374896,57.6493322],[10.1725726,57.6462818],[10.1754245,57.7367768],[10.5118282,57.7330269],[10.5152095,57.8228945],[10.6834853,57.8207722],[10.6751613,57.6412021],[10.5077045,57.6433097],[10.5039992,57.5535088],[10.671038,57.5514113],[10.6507805,57.1024538],[10.4857673,57.1045138],[10.4786236,56.9249051],[10.3143981,56.9267573],[10.3112341,56.8369269],[10.4750295,56.83509],[10.4649016,56.5656681],[10.9524239,56.5589761],[10.9479249,56.4692243],[11.1099335,56.4664675],[11.1052639,56.376833],[10.9429901,56.3795284],[10.9341235,56.1994768],[10.7719685,56.2020244],[10.7694751,56.1120103],[10.6079695,56.1150259],[10.4466742,56.116717],[10.2865948,56.118675],[10.2831527,56.0281851],[10.4439274,56.0270388],[10.4417713,55.7579243],[10.4334961,55.6693533],[10.743814,55.6646861],[10.743814,55.5712253],[10.8969041,55.5712253],[10.9051793,55.3953852],[11.0613726,55.3812841],[11.0593038,55.1124061],[11.0458567,55.0318621],[11.2030844,55.0247474],[11.2030844,55.117139],[11.0593038,55.1124061],[11.0613726,55.3812841],[11.0789572,55.5712253],[10.8969041,55.5712253],[10.9258671,55.6670198],[10.743814,55.6646861],[10.7562267,55.7579243],[10.4417713,55.7579243],[10.4439274,56.0270388],[10.4466742,56.116717],[10.6079695,56.1150259],[10.6052053,56.0247462],[10.9258671,56.0201215],[10.9197132,55.9309388],[11.0802782,55.92792],[11.0858066,56.0178284],[11.7265047,56.005058],[11.7319981,56.0952142],[12.0540333,56.0871256],[12.0608477,56.1762576],[12.7023469,56.1594405],[12.6611131,55.7114318],[12.9792318,55.7014026],[12.9612912,55.5217294],[12.3268659,55.5412096],[12.3206071,55.4513655],[12.4778226,55.447067],[12.4702432,55.3570479],[12.6269738,55.3523837],[12.6200898,55.2632576],[12.4627339,55.26722],[12.4552949,55.1778223],[12.2987046,55.1822303],[12.2897344,55.0923641],[12.6048608,55.0832904],[12.5872011,54.9036285],[12.2766618,54.9119031],[12.2610181,54.7331602],[12.1070691,54.7378161],[12.0858621,54.4681655],[11.7794953,54.4753579],[11.7837381,54.5654783],[11.1658525,54.5782155],[11.1706443,54.6686508],[10.8617173,54.6733956],[10.8651245,54.7634667],[10.7713646,54.7643888],[10.7707276,54.7372807],[10.7551428,54.7375776],[10.7544039,54.7195666],[10.7389074,54.7197588],[10.7384368,54.7108482],[10.7074486,54.7113045],[10.7041094,54.6756741],[10.5510973,54.6781698],[10.5547184,54.7670245],[10.2423994,54.7705935],[10.2459845,54.8604673],[10.0902268,54.8622134],[10.0873731,54.7723851],[9.1555798,54.7769557],[9.1562752,54.8675369],[8.5321973,54.8663765],[8.531432,54.95516],[8.3743941,54.9551655]],[[11.4577738,56.819554],[11.7849181,56.8127385],[11.7716715,56.6332796],[11.4459621,56.6401087],[11.4577738,56.819554]],[[11.3274736,57.3612962],[11.3161808,57.1818004],[11.1508692,57.1847276],[11.1456628,57.094962],[10.8157703,57.1001693],[10.8290599,57.3695272],[11.3274736,57.3612962]],[[11.5843266,56.2777928],[11.5782882,56.1880397],[11.7392309,56.1845765],[11.7456428,56.2743186],[11.5843266,56.2777928]],[[14.6825922,55.3639405],[14.8395247,55.3565231],[14.8263755,55.2671261],[15.1393406,55.2517359],[15.1532015,55.3410836],[15.309925,55.3330556],[15.295719,55.2437356],[15.1393406,55.2517359],[15.1255631,55.1623802],[15.2815819,55.1544167],[15.2535578,54.9757646],[14.6317464,55.0062496],[14.6825922,55.3639405]]],"terms_url":"http://wiki.openstreetmap.org/wiki/Vejmidte","terms_text":"Danish municipalities"},{"name":"Vienna: Beschriftungen (annotations)","type":"tms","template":"http://www.wien.gv.at/wmts/beschriftung/normal/google3857/{zoom}/{y}/{x}.png","scaleExtent":[0,19],"polygon":[[[16.17,48.1],[16.17,48.33],[16.58,48.33],[16.58,48.1],[16.17,48.1]]],"terms_url":"http://data.wien.gv.at/","terms_text":"Stadt Wien"},{"name":"Vienna: Mehrzweckkarte (general purpose)","type":"tms","template":"http://www.wien.gv.at/wmts/fmzk/pastell/google3857/{zoom}/{y}/{x}.jpeg","scaleExtent":[0,19],"polygon":[[[16.17,48.1],[16.17,48.33],[16.58,48.33],[16.58,48.1],[16.17,48.1]]],"terms_url":"http://data.wien.gv.at/","terms_text":"Stadt Wien"},{"name":"Vienna: Orthofoto (aerial image)","type":"tms","template":"http://www.wien.gv.at/wmts/lb/farbe/google3857/{zoom}/{y}/{x}.jpeg","scaleExtent":[0,19],"polygon":[[[16.17,48.1],[16.17,48.33],[16.58,48.33],[16.58,48.1],[16.17,48.1]]],"terms_url":"http://data.wien.gv.at/","terms_text":"Stadt Wien"}];
18952
18953 var presets = {"aerialway":{"fields":["aerialway"],"geometry":["point","vertex","line"],"tags":{"aerialway":"*"},"terms":["ski lift","funifor","funitel"],"searchable":false,"name":"Aerialway"},"aeroway":{"icon":"airport","fields":["aeroway"],"geometry":["point","vertex","line","area"],"tags":{"aeroway":"*"},"searchable":false,"name":"Aeroway"},"amenity":{"fields":["amenity"],"geometry":["point","vertex","area"],"tags":{"amenity":"*"},"searchable":false,"name":"Amenity"},"highway":{"fields":["highway"],"geometry":["point","vertex","line","area"],"tags":{"highway":"*"},"searchable":false,"name":"Highway"},"place":{"fields":["place"],"geometry":["point","vertex","area"],"tags":{"place":"*"},"searchable":false,"name":"Place"},"power":{"geometry":["point","vertex","line","area"],"tags":{"power":"*"},"fields":["power"],"searchable":false,"name":"Power"},"railway":{"fields":["railway"],"geometry":["point","vertex","line","area"],"tags":{"railway":"*"},"searchable":false,"name":"Railway"},"roundabout":{"geometry":["vertex","line"],"tags":{"junction":"roundabout"},"name":"Roundabout","searchable":false},"waterway":{"fields":["waterway"],"geometry":["point","vertex","line","area"],"tags":{"waterway":"*"},"searchable":false,"name":"Waterway"},"address":{"fields":["address"],"geometry":["point"],"tags":{"addr:housenumber":"*"},"addTags":{},"removeTags":{},"matchScore":0.2,"name":"Address"},"advertising/billboard":{"fields":["parallel_direction","lit"],"geometry":["point","vertex","line"],"tags":{"advertising":"billboard"},"name":"Billboard"},"aerialway/cable_car":{"geometry":["line"],"terms":["tramway","ropeway"],"fields":["aerialway/occupancy","aerialway/capacity","aerialway/duration","aerialway/heating"],"tags":{"aerialway":"cable_car"},"name":"Cable Car"},"aerialway/chair_lift":{"geometry":["line"],"fields":["aerialway/occupancy","aerialway/capacity","aerialway/duration","aerialway/bubble","aerialway/heating"],"tags":{"aerialway":"chair_lift"},"name":"Chair Lift"},"aerialway/gondola":{"geometry":["line"],"fields":["aerialway/occupancy","aerialway/capacity","aerialway/duration","aerialway/bubble","aerialway/heating"],"tags":{"aerialway":"gondola"},"name":"Gondola"},"aerialway/magic_carpet":{"geometry":["line"],"fields":["aerialway/capacity","aerialway/duration","aerialway/heating"],"tags":{"aerialway":"magic_carpet"},"name":"Magic Carpet Lift"},"aerialway/platter":{"geometry":["line"],"terms":["button lift","poma lift"],"fields":["aerialway/capacity","aerialway/duration"],"tags":{"aerialway":"platter"},"name":"Platter Lift"},"aerialway/pylon":{"geometry":["point","vertex"],"fields":["ref"],"tags":{"aerialway":"pylon"},"name":"Aerialway Pylon"},"aerialway/rope_tow":{"geometry":["line"],"terms":["handle tow","bugel lift"],"fields":["aerialway/capacity","aerialway/duration"],"tags":{"aerialway":"rope_tow"},"name":"Rope Tow Lift"},"aerialway/station":{"geometry":["point","vertex"],"fields":["aerialway/access","aerialway/summer/access","elevation"],"tags":{"aerialway":"station"},"name":"Aerialway Station"},"aerialway/t-bar":{"geometry":["line"],"fields":["aerialway/capacity","aerialway/duration"],"tags":{"aerialway":"t-bar"},"name":"T-bar Lift"},"aeroway/aerodrome":{"icon":"airport","geometry":["point","area"],"terms":["airplane","airport","aerodrome"],"fields":["ref","iata","icao","operator"],"tags":{"aeroway":"aerodrome"},"name":"Airport"},"aeroway/apron":{"icon":"airport","geometry":["area"],"terms":["ramp"],"fields":["ref","surface"],"tags":{"aeroway":"apron"},"name":"Apron"},"aeroway/gate":{"icon":"airport","geometry":["point"],"fields":["ref"],"tags":{"aeroway":"gate"},"name":"Airport gate"},"aeroway/hangar":{"geometry":["area"],"fields":["building_area"],"tags":{"aeroway":"hangar"},"name":"Hangar"},"aeroway/helipad":{"icon":"heliport","geometry":["point","area"],"terms":["helicopter","helipad","heliport"],"tags":{"aeroway":"helipad"},"name":"Helipad"},"aeroway/runway":{"geometry":["line","area"],"terms":["landing strip"],"fields":["ref","surface","length","width"],"tags":{"aeroway":"runway"},"name":"Runway"},"aeroway/taxiway":{"geometry":["line"],"fields":["ref","surface"],"tags":{"aeroway":"taxiway"},"name":"Taxiway"},"aeroway/terminal":{"geometry":["point","area"],"terms":["airport","aerodrome"],"fields":["operator","building_area"],"tags":{"aeroway":"terminal"},"name":"Airport terminal"},"amenity/register_office":{"icon":"town-hall","fields":["address","building_area","opening_hours","operator"],"geometry":["point","area"],"terms":[],"tags":{"amenity":"register_office"},"name":"Register Office","searchable":false},"amenity/swimming_pool":{"icon":"swimming","geometry":["point","vertex","area"],"tags":{"amenity":"swimming_pool"},"name":"Swimming Pool","searchable":false},"amenity/arts_centre":{"icon":"theatre","fields":["address","building_area","opening_hours"],"geometry":["point","area"],"terms":[],"tags":{"amenity":"arts_centre"},"name":"Arts Center"},"amenity/atm":{"icon":"bank","fields":["operator","currency_multi","drive_through"],"geometry":["point","vertex"],"terms":["money","cash","machine"],"tags":{"amenity":"atm"},"name":"ATM"},"amenity/bank":{"icon":"bank","fields":["atm","operator","address","building_area","opening_hours","drive_through"],"geometry":["point","area"],"terms":["credit union","check","deposit","fund","investment","repository","reserve","safe","savings","stock","treasury","trust","vault"],"tags":{"amenity":"bank"},"name":"Bank"},"amenity/bar":{"icon":"bar","fields":["operator","address","building_area","opening_hours","smoking"],"geometry":["point","area"],"terms":["dive","beer","bier","booze"],"tags":{"amenity":"bar"},"name":"Bar"},"amenity/bbq":{"fields":["covered","fuel"],"geometry":["point"],"terms":["bbq","grill"],"tags":{"amenity":"bbq"},"name":"Barbecue/Grill"},"amenity/bench":{"fields":["backrest"],"geometry":["point","vertex","line"],"terms":["seat"],"tags":{"amenity":"bench"},"name":"Bench"},"amenity/bicycle_parking":{"icon":"bicycle","fields":["bicycle_parking","capacity","operator","covered","access_simple"],"geometry":["point","vertex","area"],"terms":["bike"],"tags":{"amenity":"bicycle_parking"},"name":"Bicycle Parking"},"amenity/bicycle_rental":{"icon":"bicycle","fields":["capacity","network","operator"],"geometry":["point","vertex","area"],"terms":["bike"],"tags":{"amenity":"bicycle_rental"},"name":"Bicycle Rental"},"amenity/bicycle_repair_station":{"icon":"bicycle","fields":["operator","brand","opening_hours","fee","service/bicycle"],"geometry":["point","vertex","area"],"terms":["bike","repair","chain","pump"],"tags":{"amenity":"bicycle_repair_station"},"name":"Bicycle Repair Tool Stand"},"amenity/biergarten":{"icon":"beer","fields":["address","building_area","opening_hours","smoking"],"geometry":["point","area"],"tags":{"amenity":"biergarten"},"terms":["beer","bier","booze"],"name":"Beer Garden"},"amenity/boat_rental":{"fields":["operator"],"geometry":["point","area"],"tags":{"amenity":"boat_rental"},"name":"Boat Rental"},"amenity/bureau_de_change":{"icon":"bank","fields":["operator","currency_multi"],"geometry":["point","vertex"],"terms":["bureau de change","money changer"],"tags":{"amenity":"bureau_de_change"},"name":"Currency Exchange"},"amenity/bus_station":{"icon":"bus","fields":["building_area","operator"],"geometry":["point","area"],"tags":{"amenity":"bus_station"},"name":"Bus Station"},"amenity/cafe":{"icon":"cafe","fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"geometry":["point","area"],"terms":["bistro","coffee","tea"],"tags":{"amenity":"cafe"},"name":"Cafe"},"amenity/car_rental":{"icon":"car","fields":["operator"],"geometry":["point","area"],"tags":{"amenity":"car_rental"},"name":"Car Rental"},"amenity/car_sharing":{"icon":"car","fields":["operator","capacity"],"geometry":["point","area"],"tags":{"amenity":"car_sharing"},"name":"Car Sharing"},"amenity/car_wash":{"icon":"car","fields":["address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"amenity":"car_wash"},"name":"Car Wash"},"amenity/casino":{"fields":["operator","address","building_area","opening_hours","smoking"],"geometry":["point","area"],"terms":["gambling","roulette","craps","poker","blackjack"],"tags":{"amenity":"casino"},"name":"Casino"},"amenity/charging_station":{"icon":"car","fields":["operator","capacity"],"geometry":["point","area"],"tags":{"amenity":"charging_station"},"terms":["EV","Electric Vehicle","Supercharger"],"name":"Charging Station"},"amenity/childcare":{"icon":"school","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["daycare","orphanage","playgroup"],"tags":{"amenity":"childcare"},"name":"Nursery/Childcare"},"amenity/cinema":{"icon":"cinema","fields":["address","building_area","opening_hours"],"geometry":["point","area"],"terms":["drive-in","film","flick","movie","theater","picture","show","screen"],"tags":{"amenity":"cinema"},"name":"Cinema"},"amenity/clinic":{"icon":"hospital","fields":["address","building_area","opening_hours"],"geometry":["point","area"],"terms":["medical","urgentcare"],"tags":{"amenity":"clinic"},"name":"Clinic"},"amenity/clock":{"fields":["support","display","visibility","date"],"geometry":["point","vertex"],"tags":{"amenity":"clock"},"name":"Clock"},"amenity/college":{"icon":"college","fields":["operator","address"],"geometry":["point","area"],"terms":["university"],"tags":{"amenity":"college"},"name":"College Grounds"},"amenity/community_centre":{"icon":"town-hall","fields":["operator","address","building_area"],"geometry":["point","area"],"terms":["event","hall"],"tags":{"amenity":"community_centre"},"name":"Community Center"},"amenity/compressed_air":{"icon":"car","geometry":["point","area"],"tags":{"amenity":"compressed_air"},"name":"Compressed Air"},"amenity/courthouse":{"icon":"town-hall","fields":["operator","address","building_area"],"geometry":["point","area"],"tags":{"amenity":"courthouse"},"name":"Courthouse"},"amenity/coworking_space":{"icon":"commercial","fields":["address","building_area","opening_hours"],"geometry":["point","area"],"terms":["coworking","office"],"tags":{"amenity":"coworking_space"},"name":"Coworking Space"},"amenity/dentist":{"icon":"dentist","fields":["address","building_area","opening_hours"],"geometry":["point","area"],"terms":["tooth","teeth"],"tags":{"amenity":"dentist"},"name":"Dentist"},"amenity/doctors":{"icon":"hospital","fields":["address","building_area","opening_hours"],"geometry":["point","area"],"terms":["medic*"],"tags":{"amenity":"doctors"},"name":"Doctor"},"amenity/dojo":{"icon":"pitch","fields":["sport","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["martial arts","dojang"],"tags":{"amenity":"dojo"},"name":"Dojo / Martial Arts Academy"},"amenity/drinking_water":{"icon":"water","geometry":["point"],"tags":{"amenity":"drinking_water"},"terms":["fountain","potable"],"name":"Drinking Water"},"amenity/embassy":{"icon":"embassy","fields":["country","address","building_area"],"geometry":["point","area"],"tags":{"amenity":"embassy"},"name":"Embassy"},"amenity/fast_food":{"icon":"fast-food","fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"geometry":["point","area"],"tags":{"amenity":"fast_food"},"terms":["restaurant","takeaway"],"name":"Fast Food"},"amenity/ferry_terminal":{"icon":"ferry","fields":["network","operator","address","building_area"],"geometry":["point","vertex","area"],"terms":[],"tags":{"amenity":"ferry_terminal"},"name":"Ferry Terminal"},"amenity/fire_station":{"icon":"fire-station","fields":["operator","address","building_area"],"geometry":["point","area"],"terms":[],"tags":{"amenity":"fire_station"},"name":"Fire Station"},"amenity/fountain":{"geometry":["point","area"],"tags":{"amenity":"fountain"},"name":"Fountain"},"amenity/fuel":{"icon":"fuel","fields":["operator","address","opening_hours","fuel_multi"],"geometry":["point","area"],"terms":["petrol","fuel","gasoline","propane","diesel","lng","cng","biodiesel"],"tags":{"amenity":"fuel"},"name":"Gas Station"},"amenity/grave_yard":{"icon":"cemetery","fields":["religion","denomination"],"geometry":["point","area"],"tags":{"amenity":"grave_yard"},"name":"Graveyard"},"amenity/grit_bin":{"fields":["access_simple"],"geometry":["point","vertex"],"tags":{"amenity":"grit_bin"},"terms":["salt","sand"],"name":"Grit Bin"},"amenity/hospital":{"icon":"hospital","fields":["operator","address","emergency"],"geometry":["point","area"],"terms":["clinic","doctor","emergency room","health service","hospice","infirmary","institution","nursing home","sanatorium","sanitarium","sick","surgery","ward"],"tags":{"amenity":"hospital"},"name":"Hospital Grounds"},"amenity/hunting_stand":{"geometry":["point","vertex","area"],"terms":[],"tags":{"amenity":"hunting_stand"},"name":"Hunting Stand"},"amenity/ice_cream":{"icon":"ice-cream","fields":["address","building_area","opening_hours","takeaway","delivery"],"geometry":["point","area"],"terms":["gelato","sorbet","sherbet","frozen","yogurt"],"tags":{"amenity":"ice_cream"},"name":"Ice Cream Shop"},"amenity/internet_cafe":{"fields":["operator","address","building_area","opening_hours","smoking"],"geometry":["point","area"],"terms":["cybercafe","taxiphone","teleboutique","coffee","cafe","net","lanhouse"],"tags":{"amenity":"internet_cafe"},"name":"Internet Cafe"},"amenity/kindergarten":{"icon":"school","fields":["operator","address"],"geometry":["point","area"],"terms":["kindergarden","pre-school"],"tags":{"amenity":"kindergarten"},"name":"Preschool/Kindergarten Grounds"},"amenity/library":{"icon":"library","fields":["operator","building_area","address","opening_hours"],"geometry":["point","area"],"terms":["book"],"tags":{"amenity":"library"},"name":"Library"},"amenity/marketplace":{"fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"amenity":"marketplace"},"name":"Marketplace"},"amenity/motorcycle_parking":{"icon":"scooter","fields":["capacity","operator","covered","access_simple"],"geometry":["point","vertex","area"],"tags":{"amenity":"motorcycle_parking"},"name":"Motorcycle Parking"},"amenity/nightclub":{"icon":"bar","fields":["operator","address","building_area","opening_hours","smoking"],"geometry":["point","area"],"tags":{"amenity":"nightclub"},"terms":["disco*","night club","dancing","dance club"],"name":"Nightclub"},"amenity/parking_entrance":{"icon":"entrance","fields":["access_simple","ref"],"geometry":["vertex"],"tags":{"amenity":"parking_entrance"},"name":"Parking Garage Entrance/Exit"},"amenity/parking_space":{"fields":["capacity"],"geometry":["point","vertex","area"],"terms":[],"tags":{"amenity":"parking_space"},"name":"Parking Space"},"amenity/parking":{"icon":"parking","fields":["operator","parking","capacity","fee","access_simple","supervised","park_ride","surface","maxstay","address"],"geometry":["point","vertex","area"],"tags":{"amenity":"parking"},"terms":[],"name":"Car Parking"},"amenity/pharmacy":{"icon":"pharmacy","fields":["operator","address","building_area","opening_hours","drive_through"],"geometry":["point","area"],"tags":{"amenity":"pharmacy"},"terms":["drug*","med*","prescription"],"name":"Pharmacy"},"amenity/place_of_worship":{"icon":"place-of-worship","fields":["religion","denomination","address","building_area"],"geometry":["point","area"],"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"],"tags":{"amenity":"place_of_worship"},"name":"Place of Worship"},"amenity/place_of_worship/buddhist":{"icon":"place-of-worship","fields":["denomination","building_area","address"],"geometry":["point","area"],"terms":["stupa","vihara","monastery","temple","pagoda","zendo","dojo"],"tags":{"amenity":"place_of_worship","religion":"buddhist"},"name":"Buddhist Temple"},"amenity/place_of_worship/christian":{"icon":"religious-christian","fields":["denomination","building_area","address"],"geometry":["point","area"],"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"],"tags":{"amenity":"place_of_worship","religion":"christian"},"name":"Church"},"amenity/place_of_worship/jewish":{"icon":"religious-jewish","fields":["denomination","building_area","address"],"geometry":["point","area"],"terms":["jewish"],"tags":{"amenity":"place_of_worship","religion":"jewish"},"name":"Synagogue"},"amenity/place_of_worship/muslim":{"icon":"religious-muslim","fields":["denomination","building_area","address"],"geometry":["point","area"],"terms":["muslim"],"tags":{"amenity":"place_of_worship","religion":"muslim"},"name":"Mosque"},"amenity/planetarium":{"icon":"museum","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["museum","astronomy","observatory"],"tags":{"amenity":"planetarium"},"name":"Planetarium"},"amenity/police":{"icon":"police","fields":["operator","address","building_area"],"geometry":["point","area"],"terms":["badge","constable","constabulary","cop","detective","fed","law","enforcement","officer","patrol"],"tags":{"amenity":"police"},"name":"Police"},"amenity/post_box":{"icon":"post","fields":["operator","collection_times","drive_through","ref"],"geometry":["point","vertex"],"tags":{"amenity":"post_box"},"terms":["letter","post"],"name":"Mailbox"},"amenity/post_office":{"icon":"post","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["letter","mail"],"tags":{"amenity":"post_office"},"name":"Post Office"},"amenity/prison":{"icon":"prison","fields":["operator","address"],"geometry":["point","area"],"terms":["cell","jail"],"tags":{"amenity":"prison"},"name":"Prison Grounds"},"amenity/pub":{"icon":"beer","fields":["address","building_area","opening_hours","smoking"],"geometry":["point","area"],"tags":{"amenity":"pub"},"terms":["dive","beer","bier","booze"],"name":"Pub"},"amenity/public_bookcase":{"icon":"library","fields":["name","operator","capacity","website"],"geometry":["point","area"],"terms":["library","bookcrossing"],"tags":{"amenity":"public_bookcase"},"name":"Public Bookcase"},"amenity/ranger_station":{"fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["visitor center","visitor centre","permit center","permit centre","backcountry office","warden office","warden center"],"tags":{"amenity":"ranger_station"},"name":"Ranger Station"},"amenity/recycling_centre":{"icon":"waste-basket","fields":["operator","address","opening_hours","recycling_accepts"],"geometry":["point","area"],"terms":["bottle","can","dump","glass","garbage","rubbish","scrap","trash"],"tags":{"amenity":"recycling","recycling_type":"centre"},"name":"Recycling Center"},"amenity/recycling":{"icon":"waste-basket","fields":["recycling_type","recycling_accepts","collection_times"],"geometry":["point","area"],"terms":["bin","can","bottle","glass","garbage","rubbish","scrap","trash"],"tags":{"amenity":"recycling"},"name":"Recycling"},"amenity/restaurant":{"icon":"restaurant","fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"geometry":["point","area"],"terms":["bar","breakfast","cafe","café","canteen","coffee","dine","dining","dinner","drive-in","eat","grill","lunch","table"],"tags":{"amenity":"restaurant"},"name":"Restaurant"},"amenity/sanitary_dump_station":{"fields":["operator","access_toilets","fee","water_point"],"geometry":["point","vertex","area"],"terms":["Motor Home","Camper","Sanitary","Dump Station","Elsan","CDP","CTDP","Chemical Toilet"],"tags":{"amenity":"sanitary_dump_station"},"name":"RV Toilet Disposal"},"amenity/school":{"icon":"school","fields":["operator","address"],"geometry":["point","area"],"terms":["academy","elementary school","middle school","high school"],"tags":{"amenity":"school"},"name":"School Grounds"},"amenity/shelter":{"fields":["shelter_type","bin"],"geometry":["point","vertex","area"],"terms":["lean-to","gazebo","picnic"],"tags":{"amenity":"shelter"},"name":"Shelter"},"amenity/social_facility":{"fields":["operator","address","building_area","opening_hours","wheelchair","social_facility_for"],"geometry":["point","area"],"terms":[],"tags":{"amenity":"social_facility"},"name":"Social Facility"},"amenity/social_facility/food_bank":{"fields":["operator","address","building_area","opening_hours","social_facility_for"],"geometry":["point","area"],"terms":[],"tags":{"amenity":"social_facility","social_facility":"food_bank"},"name":"Food Bank"},"amenity/social_facility/group_home":{"fields":["operator","address","building_area","opening_hours","wheelchair","social_facility_for"],"geometry":["point","area"],"terms":["old","senior","living"],"tags":{"amenity":"social_facility","social_facility":"group_home","social_facility:for":"senior"},"name":"Elderly Group Home"},"amenity/social_facility/homeless_shelter":{"fields":["operator","address","building_area","opening_hours","wheelchair","social_facility_for"],"geometry":["point","area"],"terms":["houseless","unhoused","displaced"],"tags":{"amenity":"social_facility","social_facility":"shelter","social_facility:for":"homeless"},"name":"Homeless Shelter"},"amenity/studio":{"icon":"music","fields":["studio","address","building_area"],"geometry":["point","area"],"terms":["recording","radio","television"],"tags":{"amenity":"studio"},"name":"Studio"},"amenity/taxi":{"icon":"car","fields":["operator","capacity"],"geometry":["point","vertex","area"],"terms":["cab"],"tags":{"amenity":"taxi"},"name":"Taxi Stand"},"amenity/telephone":{"icon":"telephone","geometry":["point","vertex"],"tags":{"amenity":"telephone"},"terms":["phone"],"name":"Telephone"},"amenity/theatre":{"icon":"theatre","fields":["operator","address","building_area"],"geometry":["point","area"],"terms":["theatre","performance","play","musical"],"tags":{"amenity":"theatre"},"name":"Theater"},"amenity/toilets":{"icon":"toilets","fields":["toilets/disposal","operator","building_area","access_toilets","gender","fee","diaper"],"geometry":["point","vertex","area"],"terms":["bathroom","restroom","outhouse","privy","head","lavatory","latrine","water closet","WC","W.C."],"tags":{"amenity":"toilets"},"name":"Toilets"},"amenity/townhall":{"icon":"town-hall","fields":["operator","address","building_area"],"geometry":["point","area"],"terms":["village","city","government","courthouse","municipal"],"tags":{"amenity":"townhall"},"name":"Town Hall"},"amenity/university":{"icon":"college","fields":["operator","address"],"geometry":["point","area"],"terms":["college"],"tags":{"amenity":"university"},"name":"University Grounds"},"amenity/vending_machine/cigarettes":{"fields":["operator","payment_multi","currency_multi"],"geometry":["point"],"terms":["cigarette"],"tags":{"amenity":"vending_machine","vending":"cigarettes"},"name":"Cigarette Vending Machine"},"amenity/vending_machine/condoms":{"fields":["operator","payment_multi","currency_multi"],"geometry":["point"],"terms":["condom"],"tags":{"amenity":"vending_machine","vending":"condoms"},"name":"Condom Vending Machine"},"amenity/vending_machine/drinks":{"fields":["operator","payment_multi","currency_multi"],"geometry":["point"],"terms":["drink","soda","beverage","juice","pop"],"tags":{"amenity":"vending_machine","vending":"drinks"},"name":"Drink Vending Machine"},"amenity/vending_machine/excrement_bags":{"fields":["operator","fee","bin","payment_multi","currency_multi"],"geometry":["point"],"terms":["excrement bags","poop","dog","animal"],"tags":{"amenity":"vending_machine","vending":"excrement_bags"},"name":"Excrement Bag Vending Machine"},"amenity/vending_machine/news_papers":{"fields":["operator","fee","payment_multi","currency_multi"],"geometry":["point"],"terms":["newspaper"],"tags":{"amenity":"vending_machine","vending":"news_papers"},"name":"Newspaper Vending Machine"},"amenity/vending_machine/parcel_pickup_dropoff":{"fields":["operator","payment_multi","currency_multi"],"geometry":["point"],"terms":["parcel","mail","pickup"],"tags":{"amenity":"vending_machine","vending":"parcel_pickup;parcel_mail_in"},"name":"Parcel Pickup/Dropoff Vending Machine"},"amenity/vending_machine/parking_tickets":{"fields":["operator","payment_multi","currency_multi"],"geometry":["point"],"terms":["parking","ticket"],"tags":{"amenity":"vending_machine","vending":"parking_tickets"},"name":"Parking Ticket Vending Machine"},"amenity/vending_machine/public_transport_tickets":{"fields":["operator","payment_multi","currency_multi"],"geometry":["point"],"terms":["bus","train","ferry","rail","ticket","transportation"],"tags":{"amenity":"vending_machine","vending":"public_transport_tickets"},"name":"Transit Ticket Vending Machine"},"amenity/vending_machine/sweets":{"fields":["operator","payment_multi","currency_multi"],"geometry":["point"],"terms":["candy","gum","chip","pretzel","cookie","cracker"],"tags":{"amenity":"vending_machine","vending":"sweets"},"name":"Snack Vending Machine"},"amenity/vending_machine/vending_machine":{"fields":["vending","operator","payment_multi","currency_multi"],"geometry":["point"],"terms":[],"tags":{"amenity":"vending_machine"},"name":"Vending Machine"},"amenity/veterinary":{"icon":"dog-park","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["pet clinic","veterinarian","animal hospital","pet doctor"],"tags":{"amenity":"veterinary"},"name":"Veterinary"},"amenity/waste_basket":{"icon":"waste-basket","fields":["collection_times"],"geometry":["point","vertex","area"],"tags":{"amenity":"waste_basket"},"terms":["bin","garbage","rubbish","litter","trash"],"name":"Waste Basket"},"amenity/waste_disposal":{"icon":"waste-basket","fields":["collection_times"],"geometry":["point","vertex","area"],"tags":{"amenity":"waste_disposal"},"terms":["garbage","rubbish","litter","trash"],"name":"Garbage Dumpster"},"amenity/waste_transfer_station":{"icon":"waste-basket","fields":["operator","address","opening_hours"],"geometry":["point","area"],"terms":["dump","garbage","recycling","rubbish","scrap","trash"],"tags":{"amenity":"waste_transfer_station"},"name":"Waste Transfer Station"},"amenity/water_point":{"icon":"water","geometry":["area","vertex","point"],"tags":{"amenity":"water_point"},"name":"RV Drinking Water"},"area":{"name":"Area","tags":{"area":"yes"},"geometry":["area"],"matchScore":0.1},"area/highway":{"fields":["area/highway"],"geometry":["area"],"tags":{"area:highway":"*"},"name":"Road Surface"},"barrier":{"icon":"roadblock","geometry":["point","vertex","line","area"],"tags":{"barrier":"*"},"fields":["barrier"],"name":"Barrier"},"barrier/entrance":{"icon":"entrance","geometry":["vertex"],"tags":{"barrier":"entrance"},"name":"Entrance","searchable":false},"barrier/block":{"icon":"roadblock","fields":["access"],"geometry":["point","vertex"],"tags":{"barrier":"block"},"name":"Block"},"barrier/bollard":{"icon":"roadblock","fields":["access"],"geometry":["point","vertex","line"],"tags":{"barrier":"bollard"},"name":"Bollard"},"barrier/cattle_grid":{"icon":"prison","geometry":["vertex"],"tags":{"barrier":"cattle_grid"},"name":"Cattle Grid"},"barrier/city_wall":{"icon":"prison","geometry":["line","area"],"tags":{"barrier":"city_wall"},"name":"City Wall"},"barrier/cycle_barrier":{"icon":"roadblock","fields":["access"],"geometry":["vertex"],"tags":{"barrier":"cycle_barrier"},"name":"Cycle Barrier"},"barrier/ditch":{"icon":"roadblock","geometry":["line","area"],"tags":{"barrier":"ditch"},"name":"Trench"},"barrier/fence":{"icon":"prison","geometry":["line"],"tags":{"barrier":"fence"},"name":"Fence"},"barrier/gate":{"icon":"prison","fields":["access"],"geometry":["point","vertex","line"],"tags":{"barrier":"gate"},"name":"Gate"},"barrier/hedge":{"geometry":["line","area"],"tags":{"barrier":"hedge"},"name":"Hedge"},"barrier/kissing_gate":{"icon":"prison","fields":["access"],"geometry":["vertex"],"tags":{"barrier":"kissing_gate"},"name":"Kissing Gate"},"barrier/lift_gate":{"icon":"roadblock","fields":["access"],"geometry":["point","vertex"],"tags":{"barrier":"lift_gate"},"name":"Lift Gate"},"barrier/retaining_wall":{"geometry":["line","area"],"tags":{"barrier":"retaining_wall"},"name":"Retaining Wall"},"barrier/stile":{"icon":"roadblock","fields":["access"],"geometry":["point","vertex"],"tags":{"barrier":"stile"},"name":"Stile"},"barrier/toll_booth":{"icon":"roadblock","fields":["access"],"geometry":["vertex"],"tags":{"barrier":"toll_booth"},"name":"Toll Booth"},"barrier/wall":{"icon":"prison","geometry":["line","area"],"tags":{"barrier":"wall"},"name":"Wall"},"boundary/administrative":{"name":"Administrative Boundary","geometry":["line"],"tags":{"boundary":"administrative"},"fields":["admin_level"]},"building":{"icon":"building","fields":["building","levels","address"],"geometry":["point","area"],"tags":{"building":"*"},"matchScore":0.4,"terms":[],"name":"Building"},"building/bunker":{"fields":["address","levels"],"geometry":["area"],"tags":{"building":"bunker"},"matchScore":0.5,"name":"Bunker","searchable":false},"building/entrance":{"icon":"entrance","geometry":["vertex"],"tags":{"building":"entrance"},"name":"Entrance/Exit","searchable":false},"building/train_station":{"icon":"building","fields":["address","levels"],"geometry":["point","vertex","area"],"tags":{"building":"train_station"},"matchScore":0.5,"name":"Train Station","searchable":false},"building/apartments":{"icon":"commercial","fields":["address","levels"],"geometry":["area"],"tags":{"building":"apartments"},"matchScore":0.5,"name":"Apartments"},"building/barn":{"icon":"building","fields":["address","levels"],"geometry":["area"],"tags":{"building":"barn"},"matchScore":0.5,"name":"Barn"},"building/cabin":{"icon":"building","fields":["address","levels"],"geometry":["area"],"tags":{"building":"cabin"},"matchScore":0.5,"name":"Cabin"},"building/cathedral":{"icon":"place-of-worship","fields":["address","levels"],"geometry":["area"],"tags":{"building":"cathedral"},"matchScore":0.5,"name":"Cathedral Building"},"building/chapel":{"icon":"place-of-worship","fields":["address","levels"],"geometry":["area"],"tags":{"building":"chapel"},"matchScore":0.5,"name":"Chapel Building"},"building/church":{"icon":"place-of-worship","fields":["address","levels"],"geometry":["area"],"tags":{"building":"church"},"matchScore":0.5,"name":"Church Building"},"building/college":{"icon":"building","fields":["address","levels"],"geometry":["area"],"terms":["university"],"tags":{"building":"college"},"matchScore":0.5,"name":"College Building"},"building/commercial":{"icon":"commercial","fields":["address","levels","smoking"],"geometry":["area"],"tags":{"building":"commercial"},"matchScore":0.5,"name":"Commercial Building"},"building/construction":{"icon":"building","fields":["address","levels"],"geometry":["area"],"tags":{"building":"construction"},"matchScore":0.5,"name":"Building Under Construction"},"building/detached":{"icon":"building","fields":["address","levels"],"geometry":["area"],"tags":{"building":"detached"},"terms":["home","single","family","residence","dwelling"],"matchScore":0.5,"name":"Detached House"},"building/dormitory":{"icon":"building","fields":["address","levels","smoking"],"geometry":["area"],"tags":{"building":"dormitory"},"matchScore":0.5,"name":"Dormitory"},"building/garage":{"icon":"warehouse","fields":["capacity"],"geometry":["area"],"tags":{"building":"garage"},"matchScore":0.5,"name":"Garage"},"building/garages":{"icon":"warehouse","fields":["capacity"],"geometry":["area"],"tags":{"building":"garages"},"matchScore":0.5,"name":"Garages"},"building/greenhouse":{"icon":"building","fields":["address","levels"],"geometry":["area"],"tags":{"building":"greenhouse"},"matchScore":0.5,"name":"Greenhouse"},"building/hospital":{"icon":"building","fields":["address","levels"],"geometry":["area"],"tags":{"building":"hospital"},"matchScore":0.5,"name":"Hospital Building"},"building/hotel":{"icon":"building","fields":["address","levels","smoking"],"geometry":["area"],"tags":{"building":"hotel"},"matchScore":0.5,"name":"Hotel Building"},"building/house":{"icon":"building","fields":["address","levels"],"geometry":["area"],"tags":{"building":"house"},"terms":["home","family","residence","dwelling"],"matchScore":0.5,"name":"House"},"building/hut":{"geometry":["area"],"tags":{"building":"hut"},"matchScore":0.5,"name":"Hut"},"building/industrial":{"icon":"industrial","fields":["address","levels"],"geometry":["area"],"tags":{"building":"industrial"},"matchScore":0.5,"name":"Industrial Building"},"building/kindergarten":{"icon":"building","fields":["address","levels"],"geometry":["area"],"terms":["kindergarden","pre-school"],"tags":{"building":"kindergarten"},"matchScore":0.5,"name":"Preschool/Kindergarten Building"},"building/public":{"icon":"building","fields":["address","levels","smoking"],"geometry":["area"],"tags":{"building":"public"},"matchScore":0.5,"name":"Public Building"},"building/residential":{"icon":"building","fields":["address","levels"],"geometry":["area"],"tags":{"building":"residential"},"matchScore":0.5,"name":"Residential Building"},"building/retail":{"icon":"building","fields":["address","levels","smoking"],"geometry":["area"],"tags":{"building":"retail"},"matchScore":0.5,"name":"Retail Building"},"building/roof":{"icon":"building","fields":["address"],"geometry":["area"],"tags":{"building":"roof"},"matchScore":0.5,"name":"Roof"},"building/school":{"icon":"building","fields":["address","levels"],"geometry":["area"],"terms":["academy","elementary school","middle school","high school"],"tags":{"building":"school"},"matchScore":0.5,"name":"School Building"},"building/semidetached_house":{"icon":"building","fields":["address","levels"],"geometry":["area"],"tags":{"building":"semidetached_house"},"terms":["home","double","duplex","twin","family","residence","dwelling"],"matchScore":0.5,"name":"Semi-Detached House"},"building/shed":{"icon":"building","fields":["address","levels"],"geometry":["area"],"tags":{"building":"shed"},"matchScore":0.5,"name":"Shed"},"building/stable":{"icon":"building","fields":["address","levels"],"geometry":["area"],"tags":{"building":"stable"},"matchScore":0.5,"name":"Stable"},"building/static_caravan":{"icon":"building","fields":["address","levels"],"geometry":["area"],"tags":{"building":"static_caravan"},"matchScore":0.5,"name":"Static Mobile Home"},"building/terrace":{"icon":"building","fields":["address","levels"],"geometry":["area"],"tags":{"building":"terrace"},"terms":["home","terrace","brownstone","family","residence","dwelling"],"matchScore":0.5,"name":"Row Houses"},"building/university":{"icon":"building","fields":["address","levels"],"geometry":["area"],"terms":["college"],"tags":{"building":"university"},"matchScore":0.5,"name":"University Building"},"building/warehouse":{"icon":"warehouse","fields":["address","levels"],"geometry":["area"],"tags":{"building":"warehouse"},"matchScore":0.5,"name":"Warehouse"},"camp_site/camp_pitch":{"icon":"campsite","fields":["ref"],"geometry":["point","area"],"terms":["tent","rv"],"tags":{"camp_site":"camp_pitch"},"name":"Camp Pitch"},"craft":{"icon":"marker-stroked","fields":["craft","operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"*"},"terms":[],"name":"Craft"},"craft/jeweler":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"jeweler"},"name":"Jeweler","searchable":false},"craft/locksmith":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"locksmith"},"name":"Locksmith","searchable":false},"craft/optician":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"optician"},"name":"Optician","searchable":false},"craft/tailor":{"icon":"clothing-store","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["clothes","suit"],"tags":{"craft":"tailor"},"name":"Tailor","searchable":false},"craft/basket_maker":{"icon":"art-gallery","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"basket_maker"},"name":"Basket Maker"},"craft/beekeeper":{"icon":"farm","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"beekeeper"},"name":"Beekeeper"},"craft/blacksmith":{"icon":"farm","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"blacksmith"},"name":"Blacksmith"},"craft/boatbuilder":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"boatbuilder"},"name":"Boat Builder"},"craft/bookbinder":{"icon":"library","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["book repair"],"tags":{"craft":"bookbinder"},"name":"Bookbinder"},"craft/brewery":{"icon":"beer","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["beer","bier"],"tags":{"craft":"brewery"},"name":"Brewery"},"craft/carpenter":{"icon":"logging","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["woodworker"],"tags":{"craft":"carpenter"},"name":"Carpenter"},"craft/carpet_layer":{"icon":"square","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"carpet_layer"},"name":"Carpet Layer"},"craft/caterer":{"icon":"bakery","fields":["cuisine","operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"caterer"},"name":"Caterer"},"craft/clockmaker":{"fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"clockmaker"},"name":"Clockmaker"},"craft/confectionery":{"icon":"bakery","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["sweets","candy"],"tags":{"craft":"confectionery"},"name":"Confectionery"},"craft/dressmaker":{"icon":"clothing-store","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["seamstress"],"tags":{"craft":"dressmaker"},"name":"Dressmaker"},"craft/electrician":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["power","wire"],"tags":{"craft":"electrician"},"name":"Electrician"},"craft/gardener":{"icon":"garden","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["landscaper","grounds keeper"],"tags":{"craft":"gardener"},"name":"Gardener"},"craft/glaziery":{"icon":"fire-station","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["glass","stained-glass","window"],"tags":{"craft":"glaziery"},"name":"Glaziery"},"craft/handicraft":{"icon":"art-gallery","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"handicraft"},"name":"Handicraft"},"craft/hvac":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["heat*","vent*","air conditioning"],"tags":{"craft":"hvac"},"name":"HVAC"},"craft/insulator":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"insulation"},"name":"Insulator"},"craft/key_cutter":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"key_cutter"},"name":"Key Cutter"},"craft/metal_construction":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"metal_construction"},"name":"Metal Construction"},"craft/painter":{"icon":"art-gallery","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"painter"},"name":"Painter"},"craft/photographer":{"icon":"camera","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"photographer"},"name":"Photographer"},"craft/photographic_laboratory":{"icon":"camera","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["film"],"tags":{"craft":"photographic_laboratory"},"name":"Photographic Laboratory"},"craft/plasterer":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"plasterer"},"name":"Plasterer"},"craft/plumber":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["pipe"],"tags":{"craft":"plumber"},"name":"Plumber"},"craft/pottery":{"icon":"art-gallery","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["ceramic"],"tags":{"craft":"pottery"},"name":"Pottery"},"craft/rigger":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"rigger"},"name":"Rigger"},"craft/roofer":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"roofer"},"name":"Roofer"},"craft/saddler":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"saddler"},"name":"Saddler"},"craft/sailmaker":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"sailmaker"},"name":"Sailmaker"},"craft/sawmill":{"icon":"park","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["lumber"],"tags":{"craft":"sawmill"},"name":"Sawmill"},"craft/scaffolder":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"scaffolder"},"name":"Scaffolder"},"craft/sculpter":{"icon":"art-gallery","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"sculpter"},"name":"Sculpter"},"craft/shoemaker":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["cobbler"],"tags":{"craft":"shoemaker"},"name":"Shoemaker"},"craft/stonemason":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["masonry"],"tags":{"craft":"stonemason"},"name":"Stonemason"},"craft/sweep":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"sweep"},"name":"Chimney Sweep"},"craft/tiler":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"tiler"},"name":"Tiler"},"craft/tinsmith":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"tinsmith"},"name":"Tinsmith"},"craft/upholsterer":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"upholsterer"},"name":"Upholsterer"},"craft/watchmaker":{"fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"watchmaker"},"name":"Watchmaker"},"craft/window_construction":{"icon":"marker-stroked","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["glass"],"tags":{"craft":"window_construction"},"name":"Window Construction"},"craft/winery":{"icon":"alcohol-shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"craft":"winery"},"name":"Winery"},"embankment":{"geometry":["line"],"tags":{"embankment":"yes"},"name":"Embankment","matchScore":0.2},"emergency/designated":{"fields":[],"geometry":["line"],"tags":{"emergency":"designated"},"terms":[],"name":"Emergency Access Designated","searchable":false,"matchScore":0.01},"emergency/destination":{"fields":[],"geometry":["line"],"tags":{"emergency":"destination"},"terms":[],"name":"Emergency Access Destination","searchable":false,"matchScore":0.01},"emergency/no":{"fields":[],"geometry":["line"],"tags":{"emergency":"no"},"terms":[],"name":"Emergency Access No","searchable":false,"matchScore":0.01},"emergency/official":{"fields":[],"geometry":["line"],"tags":{"emergency":"official"},"terms":[],"name":"Emergency Access Official","searchable":false,"matchScore":0.01},"emergency/private":{"fields":[],"geometry":["line"],"tags":{"emergency":"private"},"terms":[],"name":"Emergency Access Private","searchable":false,"matchScore":0.01},"emergency/yes":{"fields":[],"geometry":["line"],"tags":{"emergency":"yes"},"terms":[],"name":"Emergency Access Yes","searchable":false,"matchScore":0.01},"emergency/ambulance_station":{"icon":"hospital","fields":["operator","building_area","address"],"geometry":["point","area"],"terms":["EMS","EMT","rescue"],"tags":{"emergency":"ambulance_station"},"name":"Ambulance Station"},"emergency/defibrillator":{"fields":["access","opening_hours","indoor","phone"],"geometry":["point"],"terms":["AED"],"tags":{"emergency":"defibrillator"},"name":"Defibrillator"},"emergency/fire_hydrant":{"icon":"fire-station","fields":["fire_hydrant/type"],"geometry":["point","vertex"],"tags":{"emergency":"fire_hydrant"},"name":"Fire Hydrant"},"emergency/phone":{"icon":"emergency-telephone","fields":["operator"],"geometry":["point","vertex"],"tags":{"emergency":"phone"},"name":"Emergency Phone"},"entrance":{"icon":"entrance","geometry":["vertex"],"tags":{"entrance":"*"},"fields":["entrance","access_simple","address"],"name":"Entrance/Exit"},"footway/crossing":{"fields":["crossing","access","surface","kerb","tactile_paving"],"geometry":["line"],"tags":{"highway":"footway","footway":"crossing"},"terms":[],"name":"Street Crossing"},"footway/crosswalk":{"icon":"highway-footway","fields":["crossing","access","surface","kerb","tactile_paving"],"geometry":["line"],"tags":{"highway":"footway","footway":"crossing","crossing":"zebra"},"terms":["zebra crossing"],"name":"Pedestrian Crosswalk"},"footway/sidewalk":{"icon":"highway-footway","fields":["surface","lit","width","structure","access"],"geometry":["line"],"tags":{"highway":"footway","footway":"sidewalk"},"terms":[],"name":"Sidewalk"},"ford":{"geometry":["vertex"],"tags":{"ford":"yes"},"name":"Ford"},"golf/bunker":{"icon":"golf","geometry":["area"],"tags":{"golf":"bunker","natural":"sand"},"terms":["hazard","bunker"],"name":"Sand Trap"},"golf/fairway":{"icon":"golf","geometry":["area"],"tags":{"golf":"fairway","landuse":"grass"},"name":"Fairway"},"golf/green":{"icon":"golf","geometry":["area"],"tags":{"golf":"green","landuse":"grass","leisure":"pitch","sport":"golf"},"name":"Putting Green"},"golf/hole":{"icon":"golf","fields":["golf_hole","par","handicap"],"geometry":["line"],"tags":{"golf":"hole"},"name":"Golf Hole"},"golf/lateral_water_hazard_area":{"icon":"golf","geometry":["area"],"tags":{"golf":"lateral_water_hazard","natural":"water"},"name":"Lateral Water Hazard"},"golf/lateral_water_hazard_line":{"icon":"golf","geometry":["line"],"tags":{"golf":"lateral_water_hazard"},"name":"Lateral Water Hazard"},"golf/rough":{"icon":"golf","geometry":["area"],"tags":{"golf":"rough","landuse":"grass"},"name":"Rough"},"golf/tee":{"icon":"golf","geometry":["area"],"tags":{"golf":"tee","landuse":"grass"},"terms":["teeing ground"],"name":"Tee Box"},"golf/water_hazard_area":{"icon":"golf","geometry":["area"],"tags":{"golf":"water_hazard","natural":"water"},"name":"Water Hazard"},"golf/water_hazard_line":{"icon":"golf","geometry":["line"],"tags":{"golf":"water_hazard"},"name":"Water Hazard"},"healthcare/blood_donation":{"icon":"hospital","fields":["operator","address","blood_components","opening_hours","ref"],"geometry":["point","area"],"terms":["blood bank","blood donation","blood transfusion","apheresis","plasmapheresis","plateletpheresis","stem cell donation"],"tags":{"healthcare":"blood_donation"},"name":"Blood Donor Center"},"highway/bridleway":{"fields":["surface","width","structure","access"],"icon":"highway-bridleway","geometry":["line"],"tags":{"highway":"bridleway"},"terms":["bridleway","equestrian","horse"],"name":"Bridle Path"},"highway/bus_stop":{"icon":"bus","fields":["network","operator","bench","shelter","covered"],"geometry":["point","vertex"],"tags":{"highway":"bus_stop"},"terms":[],"name":"Bus Stop"},"highway/corridor":{"icon":"highway-footway","fields":["width","level","access_simple"],"geometry":["line"],"tags":{"highway":"corridor"},"terms":["gallery","hall","hallway","indoor","passage","passageway"],"name":"Indoor Corridor"},"highway/crossing":{"fields":["crossing","kerb","tactile_paving"],"geometry":["vertex"],"tags":{"highway":"crossing"},"terms":[],"name":"Street Crossing"},"highway/crosswalk":{"fields":["crossing","kerb","tactile_paving"],"geometry":["vertex"],"tags":{"highway":"crossing","crossing":"zebra"},"terms":["zebra crossing"],"name":"Pedestrian Crosswalk"},"highway/cycleway":{"icon":"highway-cycleway","fields":["surface","lit","width","oneway","structure","access"],"geometry":["line"],"tags":{"highway":"cycleway"},"terms":["bike"],"name":"Cycle Path"},"highway/footway":{"icon":"highway-footway","fields":["surface","lit","width","structure","access"],"geometry":["line","area"],"terms":["hike","hiking","trackway","trail","walk"],"tags":{"highway":"footway"},"name":"Foot Path"},"highway/give_way":{"fields":["parallel_direction"],"geometry":["vertex"],"tags":{"highway":"give_way"},"terms":["give way","yield","sign"],"name":"Yield Sign"},"highway/living_street":{"icon":"highway-living-street","fields":["oneway","maxspeed","structure","access","surface","cycleway"],"geometry":["line"],"tags":{"highway":"living_street"},"name":"Living Street"},"highway/mini_roundabout":{"icon":"circle-stroked","geometry":["vertex"],"tags":{"highway":"mini_roundabout"},"fields":["clock_direction"],"name":"Mini-Roundabout"},"highway/motorway_junction":{"geometry":["vertex"],"tags":{"highway":"motorway_junction"},"fields":["ref"],"name":"Motorway Junction / Exit"},"highway/motorway_link":{"icon":"highway-motorway-link","fields":["oneway_yes","maxspeed","structure","access","surface","ref"],"geometry":["line"],"tags":{"highway":"motorway_link"},"addTags":{"highway":"motorway_link","oneway":"yes"},"removeTags":{"highway":"motorway_link","oneway":"yes"},"terms":["ramp","on ramp","off ramp"],"name":"Motorway Link"},"highway/motorway":{"icon":"highway-motorway","fields":["oneway_yes","maxspeed","structure","access","lanes","surface","ref"],"geometry":["line"],"tags":{"highway":"motorway"},"terms":[],"name":"Motorway"},"highway/path":{"icon":"highway-path","fields":["surface","width","structure","access","incline","sac_scale","trail_visibility","mtb/scale","mtb/scale/uphill","mtb/scale/imba","ref"],"geometry":["line"],"terms":["hike","hiking","trackway","trail","walk"],"tags":{"highway":"path"},"name":"Path"},"highway/pedestrian":{"icon":"highway-footway","fields":["surface","lit","width","oneway","structure","access"],"geometry":["line","area"],"tags":{"highway":"pedestrian"},"terms":[],"name":"Pedestrian Street"},"highway/primary_link":{"icon":"highway-primary-link","fields":["oneway","maxspeed","structure","access","surface","ref","cycleway"],"geometry":["line"],"tags":{"highway":"primary_link"},"terms":["ramp","on ramp","off ramp"],"name":"Primary Link"},"highway/primary":{"icon":"highway-primary","fields":["oneway","maxspeed","structure","access","lanes","surface","ref","cycleway"],"geometry":["line"],"tags":{"highway":"primary"},"terms":[],"name":"Primary Road"},"highway/raceway":{"icon":"highway-unclassified","fields":["oneway","surface","sport_racing","structure"],"geometry":["line"],"tags":{"highway":"raceway"},"addTags":{"highway":"raceway","sport":"motor"},"terms":["auto*","race*","nascar"],"name":"Motor Raceway"},"highway/residential":{"icon":"highway-residential","fields":["oneway","maxspeed","structure","access","surface","cycleway"],"geometry":["line"],"tags":{"highway":"residential"},"terms":[],"name":"Residential Road"},"highway/rest_area":{"geometry":["point","vertex","area"],"tags":{"highway":"rest_area"},"terms":["rest stop"],"name":"Rest Area"},"highway/road":{"icon":"highway-road","fields":["oneway","maxspeed","structure","access","surface"],"geometry":["line"],"tags":{"highway":"road"},"terms":[],"name":"Unknown Road"},"highway/secondary_link":{"icon":"highway-secondary-link","fields":["oneway","maxspeed","structure","access","surface","ref","cycleway"],"geometry":["line"],"tags":{"highway":"secondary_link"},"terms":["ramp","on ramp","off ramp"],"name":"Secondary Link"},"highway/secondary":{"icon":"highway-secondary","fields":["oneway","maxspeed","structure","access","lanes","surface","ref","cycleway"],"geometry":["line"],"tags":{"highway":"secondary"},"terms":[],"name":"Secondary Road"},"highway/service":{"icon":"highway-service","fields":["service","oneway","maxspeed","structure","access","surface","cycleway"],"geometry":["line"],"tags":{"highway":"service"},"terms":[],"name":"Service Road"},"highway/service/alley":{"icon":"highway-service","fields":["oneway","access","surface"],"geometry":["line"],"tags":{"highway":"service","service":"alley"},"name":"Alley"},"highway/service/drive-through":{"icon":"highway-service","fields":["oneway","access","surface"],"geometry":["line"],"tags":{"highway":"service","service":"drive-through"},"name":"Drive-Through"},"highway/service/driveway":{"icon":"highway-service","fields":["oneway","access","surface"],"geometry":["line"],"tags":{"highway":"service","service":"driveway"},"name":"Driveway"},"highway/service/emergency_access":{"icon":"highway-service","fields":["oneway","access","surface"],"geometry":["line"],"tags":{"highway":"service","service":"emergency_access"},"name":"Emergency Access"},"highway/service/parking_aisle":{"icon":"highway-service","fields":["oneway","access","surface"],"geometry":["line"],"tags":{"highway":"service","service":"parking_aisle"},"name":"Parking Aisle"},"highway/services":{"geometry":["point","vertex","area"],"tags":{"highway":"services"},"terms":["services","travel plaza","service station"],"name":"Service Area"},"highway/steps":{"fields":["surface","lit","width","incline_steps","handrail"],"icon":"highway-steps","geometry":["line"],"tags":{"highway":"steps"},"terms":["stairs","staircase"],"name":"Steps"},"highway/stop":{"fields":["stop","parallel_direction"],"geometry":["vertex"],"tags":{"highway":"stop"},"terms":["stop","halt","sign"],"name":"Stop Sign"},"highway/street_lamp":{"geometry":["point","vertex"],"tags":{"highway":"street_lamp"},"fields":["lamp_type","ref"],"terms":["streetlight","street light","lamp","light","gaslight"],"name":"Street Lamp"},"highway/tertiary_link":{"icon":"highway-tertiary-link","fields":["oneway","maxspeed","structure","access","surface","ref","cycleway"],"geometry":["line"],"tags":{"highway":"tertiary_link"},"terms":["ramp","on ramp","off ramp"],"name":"Tertiary Link"},"highway/tertiary":{"icon":"highway-tertiary","fields":["oneway","maxspeed","structure","access","lanes","surface","ref","cycleway"],"geometry":["line"],"tags":{"highway":"tertiary"},"terms":[],"name":"Tertiary Road"},"highway/track":{"icon":"highway-track","fields":["surface","width","structure","access","incline","tracktype","smoothness","mtb/scale","mtb/scale/uphill","mtb/scale/imba"],"geometry":["line"],"tags":{"highway":"track"},"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"],"name":"Unmaintained Track Road"},"highway/traffic_signals":{"geometry":["vertex"],"tags":{"highway":"traffic_signals"},"fields":["traffic_signals"],"terms":["light","stoplight","traffic light"],"name":"Traffic Signals"},"highway/trunk_link":{"icon":"highway-trunk-link","fields":["oneway","maxspeed","structure","access","surface","ref"],"geometry":["line"],"tags":{"highway":"trunk_link"},"terms":["ramp","on ramp","off ramp"],"name":"Trunk Link"},"highway/trunk":{"icon":"highway-trunk","fields":["oneway","maxspeed","structure","access","lanes","surface","ref"],"geometry":["line"],"tags":{"highway":"trunk"},"terms":[],"name":"Trunk Road"},"highway/turning_circle":{"icon":"circle-stroked","geometry":["vertex"],"tags":{"highway":"turning_circle"},"terms":["cul-de-sac"],"name":"Turning Circle"},"highway/turning_loop":{"icon":"circle","geometry":["vertex"],"tags":{"highway":"turning_loop"},"terms":["cul-de-sac"],"name":"Turning Loop (Island)"},"highway/unclassified":{"icon":"highway-unclassified","fields":["oneway","maxspeed","structure","access","surface","cycleway"],"geometry":["line"],"tags":{"highway":"unclassified"},"terms":[],"name":"Minor/Unclassified Road"},"historic":{"fields":["historic"],"geometry":["point","vertex","area"],"tags":{"historic":"*"},"name":"Historic Site"},"historic/archaeological_site":{"geometry":["point","vertex","area"],"tags":{"historic":"archaeological_site"},"name":"Archaeological Site"},"historic/boundary_stone":{"geometry":["point","vertex"],"tags":{"historic":"boundary_stone"},"name":"Boundary Stone"},"historic/castle":{"geometry":["point","area"],"tags":{"historic":"castle"},"name":"Castle"},"historic/memorial":{"icon":"monument","geometry":["point","vertex","area"],"tags":{"historic":"memorial"},"name":"Memorial"},"historic/monument":{"icon":"monument","geometry":["point","vertex","area"],"tags":{"historic":"monument"},"name":"Monument"},"historic/ruins":{"geometry":["point","vertex","area"],"tags":{"historic":"ruins"},"name":"Ruins"},"historic/wayside_cross":{"icon":"religious-christian","geometry":["point","vertex","area"],"tags":{"historic":"wayside_cross"},"name":"Wayside Cross"},"historic/wayside_shrine":{"geometry":["point","vertex","area"],"tags":{"historic":"wayside_shrine"},"name":"Wayside Shrine"},"junction":{"geometry":["vertex","area"],"tags":{"junction":"yes"},"name":"Junction"},"landuse":{"fields":["landuse"],"geometry":["area"],"tags":{"landuse":"*"},"name":"Land Use"},"landuse/farm":{"icon":"farm","fields":["crop"],"geometry":["point","area"],"tags":{"landuse":"farm"},"terms":[],"name":"Farmland","searchable":false},"landuse/allotments":{"geometry":["area"],"tags":{"landuse":"allotments"},"terms":["allotment","garden"],"name":"Community Garden"},"landuse/basin":{"geometry":["area"],"tags":{"landuse":"basin"},"terms":[],"name":"Basin"},"landuse/cemetery":{"icon":"cemetery","fields":["religion","denomination"],"geometry":["area"],"tags":{"landuse":"cemetery"},"terms":[],"name":"Cemetery"},"landuse/churchyard":{"fields":["religion","denomination"],"geometry":["area"],"tags":{"landuse":"churchyard"},"terms":[],"name":"Churchyard"},"landuse/commercial":{"icon":"commercial","geometry":["area"],"tags":{"landuse":"commercial"},"terms":[],"name":"Commercial Area"},"landuse/construction":{"fields":["construction","operator"],"geometry":["area"],"tags":{"landuse":"construction"},"terms":[],"name":"Construction"},"landuse/farmland":{"icon":"farm","fields":["crop"],"geometry":["area"],"tags":{"landuse":"farmland"},"terms":[],"name":"Farmland"},"landuse/farmyard":{"icon":"farm","fields":["crop"],"geometry":["area"],"tags":{"landuse":"farmyard"},"terms":[],"name":"Farmyard"},"landuse/forest":{"icon":"park2","fields":["leaf_type","leaf_cycle"],"geometry":["area"],"tags":{"landuse":"forest"},"terms":["tree"],"name":"Forest"},"landuse/garages":{"geometry":["area"],"tags":{"landuse":"garages"},"terms":[],"name":"Garages"},"landuse/grass":{"geometry":["area"],"tags":{"landuse":"grass"},"terms":[],"name":"Grass"},"landuse/industrial":{"icon":"industrial","geometry":["area"],"tags":{"landuse":"industrial"},"terms":[],"name":"Industrial Area"},"landuse/landfill":{"geometry":["area"],"tags":{"landuse":"landfill"},"terms":["dump"],"name":"Landfill"},"landuse/meadow":{"geometry":["area"],"tags":{"landuse":"meadow"},"terms":[],"name":"Meadow"},"landuse/military":{"geometry":["area"],"tags":{"landuse":"military"},"terms":[],"name":"Military Area"},"landuse/orchard":{"icon":"park2","fields":["trees"],"geometry":["area"],"tags":{"landuse":"orchard"},"terms":[],"name":"Orchard"},"landuse/plant_nursery":{"icon":"garden","fields":["name"],"geometry":["point","area"],"tags":{"landuse":"plant_nursery"},"terms":["vivero"],"name":"Plant Nursery"},"landuse/quarry":{"geometry":["area"],"tags":{"landuse":"quarry"},"terms":[],"name":"Quarry"},"landuse/recreation_ground":{"geometry":["area"],"tags":{"landuse":"recreation_ground"},"terms":["playing fields"],"name":"Recreation Ground"},"landuse/residential":{"icon":"building","geometry":["area"],"tags":{"landuse":"residential"},"terms":[],"name":"Residential Area"},"landuse/retail":{"icon":"shop","geometry":["area"],"tags":{"landuse":"retail"},"name":"Retail Area"},"landuse/vineyard":{"geometry":["area"],"tags":{"landuse":"vineyard"},"terms":[],"name":"Vineyard"},"leisure":{"fields":["leisure"],"geometry":["point","vertex","area"],"tags":{"leisure":"*"},"name":"Leisure"},"leisure/adult_gaming_centre":{"fields":["operator","address","building_area","opening_hours","smoking"],"geometry":["point","area"],"terms":["gambling","slot machine"],"tags":{"leisure":"adult_gaming_centre"},"name":"Adult Gaming Center"},"leisure/bird_hide":{"fields":["building_area"],"geometry":["point","area"],"tags":{"leisure":"bird_hide"},"terms":["machan","ornithology"],"name":"Bird Hide"},"leisure/bowling_alley":{"fields":["operator","address","building_area","opening_hours","smoking"],"geometry":["point","area"],"terms":[],"tags":{"leisure":"bowling_alley"},"name":"Bowling Alley"},"leisure/common":{"geometry":["point","area"],"terms":["open space"],"tags":{"leisure":"common"},"name":"Common"},"leisure/dog_park":{"icon":"dog-park","geometry":["point","area"],"terms":[],"tags":{"leisure":"dog_park"},"name":"Dog Park"},"leisure/firepit":{"geometry":["point","area"],"tags":{"leisure":"firepit"},"terms":["fireplace","campfire"],"name":"Firepit"},"leisure/fitness_centre":{"icon":"pitch","fields":["sport","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"leisure":"fitness_centre"},"terms":["health","gym","leisure","studio"],"name":"Gym / Fitness Center"},"leisure/fitness_centre/yoga":{"icon":"pitch","fields":["sport","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["studio"],"tags":{"leisure":"fitness_centre","sport":"yoga"},"name":"Yoga Studio"},"leisure/fitness_station":{"icon":"pitch","fields":["sport","address","opening_hours"],"geometry":["point","area"],"tags":{"leisure":"fitness_station"},"terms":["fitness","gym"],"name":"Outdoor Fitness Station"},"leisure/garden":{"icon":"garden","fields":["access_simple"],"geometry":["point","vertex","area"],"tags":{"leisure":"garden"},"name":"Garden"},"leisure/golf_course":{"icon":"golf","fields":["operator","address","opening_hours"],"geometry":["point","area"],"terms":["links"],"tags":{"leisure":"golf_course"},"name":"Golf Course"},"leisure/ice_rink":{"icon":"pitch","fields":["seasonal","sport_ice","operator","address","building","opening_hours"],"geometry":["point","area"],"terms":["hockey","skating","curling"],"tags":{"leisure":"ice_rink"},"name":"Ice Rink"},"leisure/marina":{"icon":"harbor","fields":["operator","address","capacity","fee","sanitary_dump_station","power_supply","internet_access"],"geometry":["point","vertex","area"],"terms":["boat"],"tags":{"leisure":"marina"},"name":"Marina"},"leisure/miniature_golf":{"icon":"golf","fields":["operator","address","opening_hours"],"geometry":["point","area"],"terms":["crazy golf","mini golf","putt-putt"],"tags":{"leisure":"miniature_golf"},"name":"Miniature Golf"},"leisure/nature_reserve":{"icon":"park","geometry":["point","area"],"tags":{"leisure":"nature_reserve"},"terms":["protected","wildlife"],"name":"Nature Reserve"},"leisure/park":{"icon":"park","geometry":["point","area"],"terms":["esplanade","estate","forest","garden","grass","green","grounds","lawn","lot","meadow","parkland","place","playground","plaza","pleasure garden","recreation area","square","tract","village green","woodland"],"tags":{"leisure":"park"},"name":"Park"},"leisure/picnic_table":{"geometry":["point"],"tags":{"leisure":"picnic_table"},"terms":["bench"],"name":"Picnic Table"},"leisure/pitch":{"icon":"pitch","fields":["sport","surface","lit"],"geometry":["point","area"],"tags":{"leisure":"pitch"},"terms":["field"],"name":"Sport Pitch"},"leisure/pitch/american_football":{"icon":"america-football","fields":["surface","lit"],"geometry":["point","area"],"tags":{"leisure":"pitch","sport":"american_football"},"terms":[],"name":"American Football Field"},"leisure/pitch/baseball":{"icon":"baseball","fields":["lit"],"geometry":["point","area"],"tags":{"leisure":"pitch","sport":"baseball"},"terms":[],"name":"Baseball Diamond"},"leisure/pitch/basketball":{"icon":"basketball","fields":["surface","hoops","lit","access_simple"],"geometry":["point","area"],"tags":{"leisure":"pitch","sport":"basketball"},"terms":[],"name":"Basketball Court"},"leisure/pitch/bowls":{"icon":"pitch","fields":["surface","lit"],"geometry":["point","area"],"tags":{"leisure":"pitch","sport":"bowls"},"terms":[],"name":"Bowling Green"},"leisure/pitch/rugby_league":{"icon":"america-football","fields":["surface","lit"],"geometry":["point","area"],"tags":{"leisure":"pitch","sport":"rugby_league"},"terms":[],"name":"Rugby League Field"},"leisure/pitch/rugby_union":{"icon":"america-football","fields":["surface","lit"],"geometry":["point","area"],"tags":{"leisure":"pitch","sport":"rugby_union"},"terms":[],"name":"Rugby Union Field"},"leisure/pitch/skateboard":{"icon":"pitch","fields":["surface","lit"],"geometry":["point","area"],"tags":{"leisure":"pitch","sport":"skateboard"},"terms":[],"name":"Skate Park"},"leisure/pitch/soccer":{"icon":"soccer","fields":["surface","lit"],"geometry":["point","area"],"tags":{"leisure":"pitch","sport":"soccer"},"terms":[],"name":"Soccer Field"},"leisure/pitch/tennis":{"icon":"tennis","fields":["surface","lit","access_simple"],"geometry":["point","area"],"tags":{"leisure":"pitch","sport":"tennis"},"terms":[],"name":"Tennis Court"},"leisure/pitch/volleyball":{"icon":"pitch","fields":["surface","lit"],"geometry":["point","area"],"tags":{"leisure":"pitch","sport":"volleyball"},"terms":[],"name":"Volleyball Court"},"leisure/playground":{"icon":"playground","geometry":["point","area"],"terms":["jungle gym","play area"],"tags":{"leisure":"playground"},"name":"Playground"},"leisure/running_track":{"icon":"pitch","fields":["surface","sport_racing","lit","width","lanes"],"geometry":["point","line"],"tags":{"leisure":"track","sport":"running"},"name":"Running Track"},"leisure/slipway":{"geometry":["point","line"],"terms":["boat launch","boat ramp"],"tags":{"leisure":"slipway"},"name":"Slipway"},"leisure/sports_centre":{"icon":"pitch","fields":["sport","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"leisure":"sports_centre"},"terms":[],"name":"Sports Center / Complex"},"leisure/sports_centre/swimming":{"icon":"swimming","fields":["access_simple","operator","address","building"],"geometry":["point","area"],"terms":["dive","water"],"tags":{"leisure":"sports_centre","sport":"swimming"},"name":"Swimming Pool Facility"},"leisure/stadium":{"icon":"pitch","fields":["sport","address"],"geometry":["point","area"],"tags":{"leisure":"stadium"},"name":"Stadium"},"leisure/swimming_pool":{"icon":"swimming","fields":["access_simple","operator","address"],"geometry":["point","area"],"terms":["dive","water"],"tags":{"leisure":"swimming_pool"},"name":"Swimming Pool"},"leisure/track":{"icon":"highway-road","fields":["surface","sport_racing","lit","width","lanes"],"geometry":["point","line"],"tags":{"leisure":"track"},"name":"Racetrack (non-Motorsport)"},"leisure/water_park":{"icon":"swimming","fields":["operator","address"],"geometry":["point","area"],"terms":["swim","pool","dive"],"tags":{"leisure":"water_park"},"name":"Water Park"},"line":{"name":"Line","tags":{},"geometry":["line"],"matchScore":0.1},"man_made":{"fields":["man_made"],"geometry":["point","vertex","line","area"],"tags":{"man_made":"*"},"name":"Man Made"},"man_made/embankment":{"geometry":["line"],"tags":{"man_made":"embankment"},"name":"Embankment","searchable":false},"man_made/adit":{"geometry":["point","area"],"fields":["operator"],"terms":["entrance","underground","mine","cave"],"tags":{"man_made":"adit"},"name":"Adit"},"man_made/breakwater":{"geometry":["line","area"],"tags":{"man_made":"breakwater"},"name":"Breakwater"},"man_made/bridge":{"geometry":["area"],"tags":{"man_made":"bridge"},"name":"Bridge"},"man_made/chimney":{"geometry":["point","area"],"tags":{"man_made":"chimney"},"name":"Chimney"},"man_made/cutline":{"geometry":["line"],"tags":{"man_made":"cutline"},"name":"Cut line"},"man_made/flagpole":{"geometry":["point"],"tags":{"man_made":"flagpole"},"name":"Flagpole","icon":"embassy"},"man_made/gasometer":{"geometry":["point","area"],"terms":["gas holder"],"tags":{"man_made":"gasometer"},"name":"Gasometer"},"man_made/groyne":{"geometry":["line","area"],"tags":{"man_made":"groyne"},"name":"Groyne"},"man_made/lighthouse":{"icon":"lighthouse","fields":["building_area"],"geometry":["point","area"],"tags":{"man_made":"lighthouse"},"name":"Lighthouse"},"man_made/mast":{"fields":["tower/type","tower/construction","height"],"geometry":["point"],"terms":["broadcast tower","cell phone tower","cell tower","guyed tower","mobile phone tower","radio tower","television tower","transmission mast","transmission tower","tv tower"],"tags":{"man_made":"mast"},"name":"Radio Mast"},"man_made/observation":{"geometry":["point","area"],"terms":["lookout tower","fire tower"],"tags":{"man_made":"tower","tower:type":"observation"},"name":"Observation Tower"},"man_made/petroleum_well":{"geometry":["point"],"terms":["drilling rig","oil derrick","oil drill","oil horse","oil rig","oil pump","petroleum well","pumpjack"],"tags":{"man_made":"petroleum_well"},"name":"Oil Well"},"man_made/pier":{"geometry":["line","area"],"terms":["dock"],"tags":{"man_made":"pier"},"name":"Pier"},"man_made/pipeline":{"icon":"pipeline-line","fields":["location","operator"],"geometry":["line"],"tags":{"man_made":"pipeline"},"name":"Pipeline"},"man_made/pumping_station":{"geometry":["point","area"],"tags":{"man_made":"pumping_station"},"name":"Pumping Station"},"man_made/silo":{"fields":["building_area","crop"],"geometry":["point","area"],"terms":["grain","corn","wheat"],"tags":{"man_made":"silo"},"name":"Silo"},"man_made/storage_tank":{"fields":["building_area","content"],"geometry":["point","area"],"terms":["water","oil","gas","petrol"],"tags":{"man_made":"storage_tank"},"name":"Storage Tank"},"man_made/surveillance":{"icon":"camera","geometry":["point"],"terms":["cctv"],"tags":{"man_made":"surveillance"},"name":"Surveillance"},"man_made/survey_point":{"icon":"monument","fields":["ref"],"geometry":["point","vertex"],"tags":{"man_made":"survey_point"},"name":"Survey Point"},"man_made/tower":{"fields":["tower/type","tower/construction","height"],"geometry":["point","area"],"tags":{"man_made":"tower"},"name":"Tower"},"man_made/wastewater_plant":{"icon":"water","fields":["operator","address"],"geometry":["point","area"],"terms":["sewage*","water treatment plant","reclamation plant"],"tags":{"man_made":"wastewater_plant"},"name":"Wastewater Plant"},"man_made/water_tower":{"icon":"water","fields":["operator"],"geometry":["point","area"],"tags":{"man_made":"water_tower"},"name":"Water Tower"},"man_made/water_well":{"fields":["operator"],"geometry":["point","area"],"tags":{"man_made":"water_well"},"name":"Water Well"},"man_made/water_works":{"icon":"water","fields":["operator","address"],"geometry":["point","area"],"tags":{"man_made":"water_works"},"name":"Water Works"},"man_made/works":{"geometry":["point","area"],"terms":["car assembly plant","aluminium processing plant","brewery","furniture manufacture factory","oil refinery","plastic recycling"],"tags":{"man_made":"works"},"name":"Works"},"military/airfield":{"icon":"airfield","geometry":["point","vertex","area"],"terms":[],"tags":{"military":"airfield"},"name":"Airfield"},"military/barracks":{"geometry":["point","vertex","area"],"terms":[],"tags":{"military":"barracks"},"name":"Barracks"},"military/bunker":{"geometry":["point","vertex","area"],"terms":[],"tags":{"military":"bunker"},"name":"Bunker"},"military/checkpoint":{"geometry":["point","vertex","area"],"terms":[],"tags":{"military":"checkpoint"},"name":"Checkpoint"},"military/danger_area":{"geometry":["point","vertex","area"],"terms":[],"tags":{"military":"danger_area"},"name":"Danger Area"},"military/naval_base":{"geometry":["point","vertex","area"],"terms":[],"tags":{"military":"naval_base"},"name":"Naval Base"},"military/obstacle_course":{"geometry":["point","vertex","area"],"terms":[],"tags":{"military":"obstacle_course"},"name":"Obstacle Course"},"military/range":{"geometry":["point","vertex","area"],"terms":[],"tags":{"military":"range"},"name":"Military Range"},"military/training_area":{"geometry":["point","vertex","area"],"terms":[],"tags":{"military":"training_area"},"name":"Training area"},"natural":{"fields":["natural"],"geometry":["point","vertex","area"],"tags":{"natural":"*"},"name":"Natural"},"natural/bay":{"geometry":["point","area"],"terms":[],"tags":{"natural":"bay"},"name":"Bay"},"natural/beach":{"fields":["surface"],"geometry":["point","area"],"terms":[],"tags":{"natural":"beach"},"name":"Beach"},"natural/cave_entrance":{"geometry":["point","area"],"fields":["fee","access_simple"],"terms":["cavern","hollow","grotto","shelter","cavity"],"tags":{"natural":"cave_entrance"},"name":"Cave Entrance"},"natural/cliff":{"geometry":["point","vertex","line","area"],"terms":[],"tags":{"natural":"cliff"},"name":"Cliff"},"natural/coastline":{"geometry":["line"],"terms":["shore"],"tags":{"natural":"coastline"},"name":"Coastline"},"natural/fell":{"geometry":["area"],"terms":[],"tags":{"natural":"fell"},"name":"Fell"},"natural/glacier":{"geometry":["area"],"terms":[],"tags":{"natural":"glacier"},"name":"Glacier"},"natural/grassland":{"geometry":["point","area"],"terms":[],"tags":{"natural":"grassland"},"name":"Grassland"},"natural/heath":{"geometry":["area"],"terms":[],"tags":{"natural":"heath"},"name":"Heath"},"natural/peak":{"icon":"triangle","fields":["elevation"],"geometry":["point","vertex"],"tags":{"natural":"peak"},"terms":["acme","aiguille","alp","climax","crest","crown","hill","mount","mountain","pinnacle","summit","tip","top"],"name":"Peak"},"natural/saddle":{"icon":"triangle-stroked","fields":["elevation"],"geometry":["point","vertex"],"tags":{"natural":"saddle"},"terms":["pass","mountain pass","top"],"name":"Saddle"},"natural/scree":{"geometry":["area"],"tags":{"natural":"scree"},"terms":["loose rocks"],"name":"Scree"},"natural/scrub":{"geometry":["area"],"tags":{"natural":"scrub"},"terms":["bush","shrubs"],"name":"Scrub"},"natural/spring":{"geometry":["point","vertex"],"terms":[],"tags":{"natural":"spring"},"name":"Spring"},"natural/tree_row":{"fields":["leaf_type","leaf_cycle","denotation"],"icon":"park","geometry":["line"],"terms":[],"tags":{"natural":"tree_row"},"name":"Tree row"},"natural/tree":{"fields":["leaf_type_singular","leaf_cycle_singular","denotation"],"icon":"park","geometry":["point","vertex"],"terms":[],"tags":{"natural":"tree"},"name":"Tree"},"natural/volcano":{"icon":"triangle","fields":["elevation"],"geometry":["point","vertex"],"tags":{"natural":"volcano"},"terms":["mountain","crater"],"name":"Volcano"},"natural/water":{"fields":["water"],"geometry":["area"],"tags":{"natural":"water"},"icon":"water","name":"Water"},"natural/water/lake":{"geometry":["area"],"tags":{"natural":"water","water":"lake"},"terms":["lakelet","loch","mere"],"icon":"water","name":"Lake"},"natural/water/pond":{"geometry":["area"],"tags":{"natural":"water","water":"pond"},"terms":["lakelet","millpond","tarn","pool","mere"],"icon":"water","name":"Pond"},"natural/water/reservoir":{"geometry":["area"],"tags":{"natural":"water","water":"reservoir"},"icon":"water","name":"Reservoir"},"natural/wetland":{"icon":"wetland","fields":["wetland"],"geometry":["point","area"],"tags":{"natural":"wetland"},"terms":[],"name":"Wetland"},"natural/wood":{"icon":"park2","fields":["leaf_type","leaf_cycle"],"geometry":["point","area"],"tags":{"natural":"wood"},"terms":["tree"],"name":"Wood"},"office":{"icon":"commercial","fields":["office","address","building_area","opening_hours","smoking"],"geometry":["point","vertex","area"],"tags":{"office":"*"},"terms":[],"name":"Office"},"office/travel_agent":{"icon":"suitcase","fields":["address","building_area","opening_hours"],"geometry":["point","vertex","area"],"tags":{"office":"travel_agent"},"terms":[],"name":"Travel Agency","searchable":false},"office/accountant":{"icon":"commercial","fields":["address","building_area","opening_hours"],"geometry":["point","vertex","area"],"tags":{"office":"accountant"},"terms":[],"name":"Accountant"},"office/administrative":{"icon":"commercial","fields":["address","building_area","opening_hours"],"geometry":["point","vertex","area"],"tags":{"office":"administrative"},"terms":[],"name":"Administrative Office"},"office/architect":{"icon":"commercial","fields":["address","building_area","opening_hours"],"geometry":["point","vertex","area"],"tags":{"office":"architect"},"terms":[],"name":"Architect"},"office/company":{"icon":"commercial","fields":["address","building_area","opening_hours","smoking"],"geometry":["point","vertex","area"],"tags":{"office":"company"},"terms":[],"name":"Company Office"},"office/educational_institution":{"icon":"commercial","fields":["address","building_area","opening_hours"],"geometry":["point","vertex","area"],"tags":{"office":"educational_institution"},"terms":[],"name":"Educational Institution"},"office/employment_agency":{"icon":"commercial","fields":["address","building_area","opening_hours"],"geometry":["point","vertex","area"],"tags":{"office":"employment_agency"},"terms":["job"],"name":"Employment Agency"},"office/estate_agent":{"icon":"commercial","fields":["address","building_area","opening_hours"],"geometry":["point","vertex","area"],"tags":{"office":"estate_agent"},"terms":[],"name":"Real Estate Office"},"office/financial":{"icon":"commercial","fields":["address","building_area","opening_hours"],"geometry":["point","vertex","area"],"tags":{"office":"financial"},"terms":[],"name":"Financial Office"},"office/government":{"icon":"commercial","fields":["address","building_area","opening_hours"],"geometry":["point","vertex","area"],"tags":{"office":"government"},"terms":[],"name":"Government Office"},"office/government/register_office":{"icon":"town-hall","fields":["address","building_area","opening_hours","operator"],"geometry":["point","area"],"terms":["clerk","marriage","death","birth","certificate"],"tags":{"office":"government","government":"register_office"},"name":"Register Office"},"office/insurance":{"icon":"commercial","fields":["address","building_area","opening_hours"],"geometry":["point","vertex","area"],"tags":{"office":"insurance"},"terms":[],"name":"Insurance Office"},"office/it":{"icon":"commercial","fields":["address","building_area","opening_hours"],"geometry":["point","vertex","area"],"tags":{"office":"it"},"terms":[],"name":"IT Office"},"office/lawyer":{"icon":"commercial","fields":["address","building_area","opening_hours"],"geometry":["point","vertex","area"],"tags":{"office":"lawyer"},"terms":[],"name":"Law Office"},"office/newspaper":{"icon":"commercial","fields":["address","building_area","opening_hours"],"geometry":["point","vertex","area"],"tags":{"office":"newspaper"},"terms":[],"name":"Newspaper"},"office/ngo":{"icon":"commercial","fields":["address","building_area","opening_hours","smoking"],"geometry":["point","vertex","area"],"tags":{"office":"ngo"},"terms":[],"name":"NGO Office"},"office/physician":{"icon":"commercial","fields":["address","building_area","opening_hours"],"geometry":["point","vertex","area"],"tags":{"office":"physician"},"terms":[],"name":"Physician"},"office/political_party":{"icon":"commercial","fields":["address","building_area","opening_hours"],"geometry":["point","vertex","area"],"tags":{"office":"political_party"},"terms":[],"name":"Political Party"},"office/research":{"icon":"commercial","fields":["address","building_area","opening_hours"],"geometry":["point","vertex","area"],"tags":{"office":"research"},"terms":[],"name":"Research Office"},"office/telecommunication":{"icon":"commercial","fields":["address","building_area","opening_hours"],"geometry":["point","vertex","area"],"tags":{"office":"telecommunication"},"terms":[],"name":"Telecom Office"},"office/therapist":{"icon":"commercial","fields":["address","building_area","opening_hours"],"geometry":["point","vertex","area"],"tags":{"office":"therapist"},"terms":[],"name":"Therapist"},"piste":{"icon":"skiing","fields":["piste/type","piste/difficulty","piste/grooming","oneway","lit"],"geometry":["point","line","area"],"terms":["ski","sled","sleigh","snowboard","nordic","downhill","snowmobile"],"tags":{"piste:type":"*"},"name":"Piste/Ski Trail"},"place/city":{"icon":"city","fields":["population"],"geometry":["point","area"],"tags":{"place":"city"},"name":"City"},"place/farm":{"icon":"farm","geometry":["point","area"],"tags":{"place":"farm"},"name":"Farm"},"place/hamlet":{"icon":"triangle-stroked","fields":["population"],"geometry":["point","area"],"tags":{"place":"hamlet"},"name":"Hamlet"},"place/island":{"geometry":["point","area"],"terms":["archipelago","atoll","bar","cay","isle","islet","key","reef"],"tags":{"place":"island"},"name":"Island"},"place/isolated_dwelling":{"geometry":["point","area"],"tags":{"place":"isolated_dwelling"},"name":"Isolated Dwelling"},"place/locality":{"icon":"marker","geometry":["point","area"],"tags":{"place":"locality"},"name":"Locality"},"place/neighbourhood":{"icon":"triangle-stroked","fields":["population"],"geometry":["point","area"],"tags":{"place":"neighbourhood"},"terms":["neighbourhood"],"name":"Neighborhood"},"place/suburb":{"icon":"triangle-stroked","fields":["population"],"geometry":["point","area"],"tags":{"place":"suburb"},"terms":["Boro","Quarter"],"name":"Borough"},"place/town":{"icon":"town","fields":["population"],"geometry":["point","area"],"tags":{"place":"town"},"name":"Town"},"place/village":{"icon":"village","fields":["population"],"geometry":["point","area"],"tags":{"place":"village"},"name":"Village"},"point":{"name":"Point","tags":{},"geometry":["point"],"matchScore":0.1},"power/sub_station":{"fields":["substation","operator","building"],"geometry":["point","area"],"tags":{"power":"sub_station"},"name":"Substation","searchable":false},"power/generator":{"fields":["operator","generator/source","generator/method","generator/type"],"geometry":["point","vertex","area"],"tags":{"power":"generator"},"name":"Power Generator"},"power/line":{"geometry":["line"],"tags":{"power":"line"},"name":"Power Line","icon":"power-line"},"power/minor_line":{"geometry":["line"],"tags":{"power":"minor_line"},"name":"Minor Power Line","icon":"power-line"},"power/pole":{"geometry":["vertex"],"tags":{"power":"pole"},"name":"Power Pole"},"power/substation":{"fields":["substation","operator","building"],"geometry":["point","area"],"tags":{"power":"substation"},"name":"Substation"},"power/tower":{"geometry":["vertex"],"tags":{"power":"tower"},"name":"High-Voltage Tower"},"power/transformer":{"geometry":["point","vertex","area"],"tags":{"power":"transformer"},"name":"Transformer"},"public_transport/platform":{"fields":["ref","network","operator","shelter"],"geometry":["point","vertex","line","area"],"tags":{"public_transport":"platform"},"name":"Platform"},"public_transport/stop_position":{"icon":"bus","fields":["ref","network","operator"],"geometry":["vertex"],"tags":{"public_transport":"stop_position"},"name":"Stop Position"},"railway/abandoned":{"icon":"railway-abandoned","geometry":["line"],"tags":{"railway":"abandoned"},"fields":["structure","service_rail"],"terms":[],"name":"Abandoned Railway"},"railway/crossing":{"icon":"cross","geometry":["vertex"],"tags":{"railway":"crossing"},"terms":["crossing","pedestrian crossing","railroad crossing","level crossing","grade crossing","path through railroad","train crossing"],"name":"Railway Crossing (Path)"},"railway/disused":{"icon":"railway-disused","geometry":["line"],"tags":{"railway":"disused"},"fields":["structure","service_rail"],"terms":[],"name":"Disused Railway"},"railway/funicular":{"geometry":["line"],"terms":["venicular","cliff railway","cable car","cable railway","funicular railway"],"fields":["structure","gauge","service_rail"],"tags":{"railway":"funicular"},"icon":"railway-rail","name":"Funicular"},"railway/halt":{"icon":"rail","geometry":["point","vertex"],"tags":{"railway":"halt"},"name":"Railway Halt","terms":["break","interrupt","rest","wait","interruption"]},"railway/level_crossing":{"icon":"cross","geometry":["vertex"],"tags":{"railway":"level_crossing"},"terms":["crossing","railroad crossing","level crossing","grade crossing","road through railroad","train crossing"],"name":"Railway Crossing (Road)"},"railway/monorail":{"icon":"railway-monorail","geometry":["line"],"tags":{"railway":"monorail"},"fields":["structure","electrified","service_rail"],"terms":[],"name":"Monorail"},"railway/narrow_gauge":{"icon":"railway-rail","geometry":["line"],"tags":{"railway":"narrow_gauge"},"fields":["structure","gauge","electrified","service_rail"],"terms":["narrow gauge railway","narrow gauge railroad"],"name":"Narrow Gauge Rail"},"railway/platform":{"geometry":["point","vertex","line","area"],"tags":{"railway":"platform"},"name":"Railway Platform"},"railway/rail":{"icon":"railway-rail","geometry":["line"],"tags":{"railway":"rail"},"fields":["structure","gauge","electrified","maxspeed","service_rail"],"terms":[],"name":"Rail"},"railway/station":{"icon":"rail","fields":["network","operator","address","building_area"],"geometry":["point","vertex","area"],"tags":{"railway":"station"},"terms":["train station","station"],"name":"Railway Station"},"railway/subway_entrance":{"icon":"rail-metro","geometry":["point"],"tags":{"railway":"subway_entrance"},"terms":[],"name":"Subway Entrance"},"railway/subway":{"icon":"railway-subway","geometry":["line"],"tags":{"railway":"subway"},"fields":["structure","gauge","electrified","service_rail"],"terms":[],"name":"Subway"},"railway/tram":{"icon":"railway-light-rail","geometry":["line"],"tags":{"railway":"tram"},"fields":["structure","gauge","electrified","service_rail"],"terms":["streetcar"],"name":"Tram"},"relation":{"name":"Relation","icon":"relation","tags":{},"geometry":["relation"],"fields":["relation"]},"route/ferry":{"icon":"ferry-line","geometry":["line"],"tags":{"route":"ferry"},"name":"Ferry Route"},"shop":{"icon":"shop","fields":["shop","operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"*"},"terms":[],"name":"Shop"},"shop/fishmonger":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"fishmonger"},"name":"Fishmonger","searchable":false},"shop/vacant":{"icon":"shop","fields":["address","building_area"],"geometry":["point","area"],"tags":{"shop":"vacant"},"name":"Vacant Shop","searchable":false},"shop/alcohol":{"icon":"alcohol-shop","fields":["operator","address","building_area","opening_hours","drive_through"],"geometry":["point","area"],"terms":["alcohol","beer","booze","wine"],"tags":{"shop":"alcohol"},"name":"Liquor Store"},"shop/anime":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"anime"},"terms":["manga","japan","cosplay","figurine","dakimakura"],"name":"Anime Shop"},"shop/antiques":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"antiques"},"name":"Antiques Shop"},"shop/art":{"icon":"shop","fields":["artwork_type","operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["art*","exhibit*","gallery"],"tags":{"shop":"art"},"name":"Art Store"},"shop/baby_goods":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"baby_goods"},"name":"Baby Goods Store"},"shop/bag":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["handbag","purse"],"tags":{"shop":"bag"},"name":"Bag/Luggage Store"},"shop/bakery":{"icon":"bakery","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"bakery"},"name":"Bakery"},"shop/bathroom_furnishing":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"bathroom_furnishing"},"name":"Bathroom Furnishing Store"},"shop/beauty":{"icon":"shop","fields":["operator","address","building_area","opening_hours","beauty"],"geometry":["point","area"],"terms":["spa","salon","tanning"],"tags":{"shop":"beauty"},"name":"Beauty Shop"},"shop/beauty/nails":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["manicure","pedicure"],"tags":{"shop":"beauty","beauty":"nails"},"name":"Nail Salon"},"shop/beauty/tanning":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"beauty","beauty":"tanning"},"name":"Tanning Salon"},"shop/bed":{"icon":"lodging","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"bed"},"name":"Bedding/Mattress Store"},"shop/beverages":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"beverages"},"name":"Beverage Store"},"shop/bicycle":{"icon":"bicycle","fields":["operator","address","building_area","opening_hours","service/bicycle"],"geometry":["point","area"],"terms":["bike","repair"],"tags":{"shop":"bicycle"},"name":"Bicycle Shop"},"shop/bookmaker":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["betting"],"tags":{"shop":"bookmaker"},"name":"Bookmaker"},"shop/books":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"books"},"name":"Book Store"},"shop/boutique":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"boutique"},"name":"Boutique"},"shop/butcher":{"icon":"slaughterhouse","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["meat"],"tags":{"shop":"butcher"},"name":"Butcher"},"shop/candles":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"candles"},"name":"Candle Shop"},"shop/car_parts":{"icon":"car","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["auto"],"tags":{"shop":"car_parts"},"name":"Car Parts Store"},"shop/car_repair":{"icon":"car","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["auto","garage","service"],"tags":{"shop":"car_repair"},"name":"Car Repair Shop"},"shop/car":{"icon":"car","fields":["operator","address","building_area","opening_hours","second_hand"],"geometry":["point","area"],"terms":["auto"],"tags":{"shop":"car"},"name":"Car Dealership"},"shop/carpet":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["rug"],"tags":{"shop":"carpet"},"name":"Carpet Store"},"shop/charity":{"icon":"shop","fields":["operator","address","building_area","opening_hours","second_hand"],"geometry":["point","area"],"terms":["thrift","op shop","nonprofit"],"tags":{"shop":"charity"},"name":"Charity Store"},"shop/cheese":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"cheese"},"name":"Cheese Store"},"shop/chemist":{"icon":"grocery","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"chemist"},"terms":["med*","drug*","gift"],"name":"Drugstore"},"shop/chocolate":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"chocolate"},"name":"Chocolate Store"},"shop/clothes":{"icon":"clothing-store","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"clothes"},"name":"Clothing Store"},"shop/coffee":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"coffee"},"name":"Coffee Store"},"shop/computer":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"computer"},"name":"Computer Store"},"shop/confectionery":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"confectionery"},"name":"Candy Store"},"shop/convenience":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"convenience"},"name":"Convenience Store"},"shop/copyshop":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"copyshop"},"name":"Copy Store"},"shop/cosmetics":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"cosmetics"},"name":"Cosmetics Store"},"shop/craft":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"craft"},"terms":["art*","paint*","frame"],"name":"Arts and Crafts Store"},"shop/curtain":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["drape*","window"],"tags":{"shop":"curtain"},"name":"Curtain Store"},"shop/dairy":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["milk","egg","cheese"],"tags":{"shop":"dairy"},"name":"Dairy Store"},"shop/deli":{"icon":"restaurant","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["lunch","meat","sandwich"],"tags":{"shop":"deli"},"name":"Deli"},"shop/department_store":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"department_store"},"name":"Department Store"},"shop/doityourself":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"doityourself"},"name":"DIY Store"},"shop/dry_cleaning":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"dry_cleaning"},"name":"Dry Cleaner"},"shop/e-cigarette":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"e-cigarette"},"terms":["electronic","vapor"],"name":"E-Cigarette Shop"},"shop/electronics":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["appliance","audio","computer","tv"],"tags":{"shop":"electronics"},"name":"Electronics Store"},"shop/erotic":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["sex","porn"],"tags":{"shop":"erotic"},"name":"Erotic Store"},"shop/fabric":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["sew"],"tags":{"shop":"fabric"},"name":"Fabric Store"},"shop/farm":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["farm shop","farm stand"],"tags":{"shop":"farm"},"name":"Produce Stand"},"shop/fashion":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"fashion"},"name":"Fashion Store"},"shop/florist":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["flower"],"tags":{"shop":"florist"},"name":"Florist"},"shop/frame":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"frame"},"terms":["art*","paint*","photo*","frame"],"name":"Framing Shop"},"shop/funeral_directors":{"icon":"cemetery","fields":["operator","address","building_area","religion","denomination"],"geometry":["point","area"],"terms":["undertaker","memorial home"],"tags":{"shop":"funeral_directors"},"name":"Funeral Home"},"shop/furnace":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["oven","stove"],"tags":{"shop":"furnace"},"name":"Furnace Store"},"shop/furniture":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["chair","sofa","table"],"tags":{"shop":"furniture"},"name":"Furniture Store"},"shop/garden_centre":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["landscape","mulch","shrub","tree"],"tags":{"shop":"garden_centre"},"name":"Garden Center"},"shop/gift":{"icon":"gift","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["souvenir"],"tags":{"shop":"gift"},"name":"Gift Shop"},"shop/greengrocer":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["fruit","vegetable"],"tags":{"shop":"greengrocer"},"name":"Greengrocer"},"shop/hairdresser":{"icon":"hairdresser","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["barber"],"tags":{"shop":"hairdresser"},"name":"Hairdresser"},"shop/hardware":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"hardware"},"name":"Hardware Store"},"shop/hearing_aids":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"hearing_aids"},"name":"Hearing Aids Store"},"shop/herbalist":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"herbalist"},"name":"Herbalist"},"shop/hifi":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["stereo","video"],"tags":{"shop":"hifi"},"name":"Hifi Store"},"shop/houseware":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["home","household"],"tags":{"shop":"houseware"},"name":"Houseware Store"},"shop/interior_decoration":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"interior_decoration"},"name":"Interior Decoration Store"},"shop/jewelry":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["diamond","gem","ring"],"tags":{"shop":"jewelry"},"name":"Jeweler"},"shop/kiosk":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"kiosk"},"name":"News Kiosk"},"shop/kitchen":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"kitchen"},"name":"Kitchen Design Store"},"shop/laundry":{"icon":"laundry","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"laundry"},"name":"Laundry"},"shop/leather":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"leather"},"name":"Leather Store"},"shop/locksmith":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["key","lockpick"],"tags":{"shop":"locksmith"},"name":"Locksmith"},"shop/lottery":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"lottery"},"name":"Lottery Shop"},"shop/mall":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["shopping"],"tags":{"shop":"mall"},"name":"Mall"},"shop/massage":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"massage"},"name":"Massage Shop"},"shop/medical_supply":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"medical_supply"},"name":"Medical Supply Store"},"shop/mobile_phone":{"icon":"mobilephone","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"mobile_phone"},"name":"Mobile Phone Store"},"shop/money_lender":{"icon":"bank","fields":["operator","address","building_area","opening_hours","currency_multi"],"geometry":["point","area"],"tags":{"shop":"money_lender"},"name":"Money Lender"},"shop/motorcycle":{"icon":"scooter","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["bike"],"tags":{"shop":"motorcycle"},"name":"Motorcycle Dealership"},"shop/music":{"icon":"music","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["CD","vinyl"],"tags":{"shop":"music"},"name":"Music Store"},"shop/musical_instrument":{"icon":"music","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["guitar"],"tags":{"shop":"musical_instrument"},"name":"Musical Instrument Store"},"shop/newsagent":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"newsagent"},"name":"Newspaper/Magazine Shop"},"shop/nutrition_supplements":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"nutrition_supplements"},"name":"Nutrition Supplements Store"},"shop/optician":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["eye","glasses"],"tags":{"shop":"optician"},"name":"Optician"},"shop/organic":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"supermarket","organic":"only"},"name":"Organic Goods Store"},"shop/outdoor":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["camping","climbing","hiking"],"tags":{"shop":"outdoor"},"name":"Outdoors Store"},"shop/paint":{"icon":"water","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"paint"},"name":"Paint Store"},"shop/pastry":{"icon":"bakery","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"pastry"},"terms":["patisserie","cake shop","cakery"],"name":"Pastry Shop"},"shop/pawnbroker":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"pawnbroker"},"name":"Pawn Shop"},"shop/pet":{"icon":"dog-park","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["cat","dog","fish"],"tags":{"shop":"pet"},"name":"Pet Store"},"shop/photo":{"icon":"camera","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["camera","film"],"tags":{"shop":"photo"},"name":"Photography Store"},"shop/pyrotechnics":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"pyrotechnics"},"name":"Fireworks Store"},"shop/radiotechnics":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"radiotechnics"},"name":"Radio/Electronic Component Store"},"shop/religion":{"icon":"shop","fields":["operator","address","building_area","opening_hours","religion","denomination"],"geometry":["point","area"],"tags":{"shop":"religion"},"name":"Religious Store"},"shop/scuba_diving":{"icon":"swimming","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"scuba_diving"},"name":"Scuba Diving Shop"},"shop/seafood":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["fishmonger"],"tags":{"shop":"seafood"},"name":"Seafood Shop"},"shop/second_hand":{"icon":"shop","fields":["operator","address","building_area","opening_hours","second_hand"],"geometry":["point","area"],"terms":["secondhand","second hand","resale","thrift","used"],"tags":{"shop":"second_hand"},"name":"Consignment/Thrift Store"},"shop/shoes":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"shoes"},"name":"Shoe Store"},"shop/sports":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"sports"},"name":"Sporting Goods Store"},"shop/stationery":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["card","paper"],"tags":{"shop":"stationery"},"name":"Stationery Store"},"shop/storage_rental":{"icon":"shop","fields":["operator","address","building","opening_hours"],"geometry":["point","area"],"tags":{"shop":"storage_rental"},"name":"Storage Rental"},"shop/supermarket":{"icon":"grocery","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["grocery","store","shop"],"tags":{"shop":"supermarket"},"name":"Supermarket"},"shop/tailor":{"icon":"clothing-store","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["clothes","suit"],"tags":{"shop":"tailor"},"name":"Tailor"},"shop/tattoo":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"tattoo"},"name":"Tattoo Parlor"},"shop/tea":{"icon":"cafe","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"tea"},"name":"Tea Store"},"shop/ticket":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"ticket"},"name":"Ticket Seller"},"shop/tobacco":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"tobacco"},"name":"Tobacco Shop"},"shop/toys":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"toys"},"name":"Toy Store"},"shop/travel_agency":{"icon":"suitcase","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"travel_agency"},"name":"Travel Agency"},"shop/tyres":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"tyres"},"name":"Tire Store"},"shop/vacuum_cleaner":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"vacuum_cleaner"},"name":"Vacuum Cleaner Store"},"shop/variety_store":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"variety_store"},"name":"Variety Store"},"shop/video_games":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"video_games"},"name":"Video Game Store"},"shop/video":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["DVD"],"tags":{"shop":"video"},"name":"Video Store"},"shop/water_sports":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"water_sports"},"name":"Watersport/Swim Shop"},"shop/weapons":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["ammo","gun","knife","knives"],"tags":{"shop":"weapons"},"name":"Weapon Shop"},"shop/window_blind":{"icon":"shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"window_blind"},"name":"Window Blind Store"},"shop/wine":{"icon":"alcohol-shop","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"tags":{"shop":"wine"},"name":"Wine Shop"},"tourism":{"fields":["tourism"],"geometry":["point","vertex","area"],"tags":{"tourism":"*"},"name":"Tourism"},"tourism/alpine_hut":{"icon":"lodging","fields":["operator","address","building_area"],"geometry":["point","area"],"tags":{"tourism":"alpine_hut"},"name":"Alpine Hut"},"tourism/apartment":{"icon":"lodging","fields":["operator","address","building_area","smoking","rooms","internet_access","internet_access/fee"],"geometry":["point","area"],"tags":{"tourism":"apartment"},"name":"Guest Apartment / Condo"},"tourism/artwork":{"icon":"art-gallery","fields":["artwork_type","artist"],"geometry":["point","vertex","area"],"tags":{"tourism":"artwork"},"terms":["mural","sculpture","statue"],"name":"Artwork"},"tourism/attraction":{"icon":"monument","fields":["operator","address"],"geometry":["point","vertex","area"],"tags":{"tourism":"attraction"},"name":"Tourist Attraction"},"tourism/camp_site":{"icon":"campsite","fields":["operator","address","capacity","fee"],"geometry":["point","vertex","area"],"terms":["tent","rv"],"tags":{"tourism":"camp_site"},"name":"Campground"},"tourism/caravan_site":{"icon":"bus","fields":["operator","address","capacity","fee","sanitary_dump_station","power_supply","internet_access"],"geometry":["point","vertex","area"],"terms":["Motor Home","Camper"],"tags":{"tourism":"caravan_site"},"name":"RV Park"},"tourism/chalet":{"icon":"lodging","fields":["operator","address","building_area","smoking"],"geometry":["point","area"],"tags":{"tourism":"chalet"},"name":"Chalet"},"tourism/gallery":{"icon":"art-gallery","fields":["artwork_type","operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["art*","exhibit*","paint*","photo*","sculpt*"],"tags":{"tourism":"gallery"},"name":"Art Gallery"},"tourism/guest_house":{"icon":"lodging","fields":["operator","address","building_area","smoking","rooms","internet_access","internet_access/fee"],"geometry":["point","area"],"tags":{"tourism":"guest_house"},"terms":["B&B","Bed and Breakfast"],"name":"Guest House"},"tourism/hostel":{"icon":"lodging","fields":["operator","address","building_area","smoking","rooms","internet_access","internet_access/fee"],"geometry":["point","area"],"tags":{"tourism":"hostel"},"name":"Hostel"},"tourism/hotel":{"icon":"lodging","fields":["operator","address","building_area","smoking","stars","rooms","internet_access","internet_access/fee"],"geometry":["point","area"],"tags":{"tourism":"hotel"},"name":"Hotel"},"tourism/information":{"fields":["information","operator","address","building_area"],"geometry":["point","vertex","area"],"tags":{"tourism":"information"},"name":"Information"},"tourism/information/board":{"fields":["operator","board_type"],"geometry":["point","vertex"],"tags":{"tourism":"information","information":"board"},"name":"Information Board"},"tourism/information/guidepost":{"fields":["operator","ref"],"geometry":["point","vertex"],"tags":{"tourism":"information","information":"guidepost"},"name":"Guidepost"},"tourism/information/map":{"fields":["operator","map_type","map_size"],"geometry":["point","vertex"],"tags":{"tourism":"information","information":"map"},"name":"Map"},"tourism/information/office":{"fields":["operator","address","building_area"],"geometry":["point","vertex","area"],"tags":{"tourism":"information","information":"office"},"name":"Tourist Information Office"},"tourism/motel":{"icon":"lodging","fields":["operator","address","building_area","smoking","rooms","internet_access","internet_access/fee"],"geometry":["point","area"],"tags":{"tourism":"motel"},"name":"Motel"},"tourism/museum":{"icon":"museum","fields":["operator","address","building_area","opening_hours"],"geometry":["point","area"],"terms":["art*","exhibit*","gallery","foundation","hall","institution","paint*","photo*","sculpt*"],"tags":{"tourism":"museum"},"name":"Museum"},"tourism/picnic_site":{"icon":"park","fields":["operator","address","smoking"],"geometry":["point","vertex","area"],"terms":["camp"],"tags":{"tourism":"picnic_site"},"name":"Picnic Site"},"tourism/theme_park":{"fields":["operator","address","opening_hours"],"geometry":["point","area"],"tags":{"tourism":"theme_park"},"name":"Theme Park"},"tourism/viewpoint":{"geometry":["point","vertex"],"tags":{"tourism":"viewpoint"},"name":"Viewpoint"},"tourism/zoo":{"icon":"zoo","fields":["operator","address","opening_hours"],"geometry":["point","area"],"tags":{"tourism":"zoo"},"name":"Zoo"},"traffic_calming":{"fields":["traffic_calming","parallel_direction"],"geometry":["vertex","line"],"tags":{"traffic_calming":"*"},"terms":["bump","hump","slow","speed"],"name":"Traffic Calming"},"traffic_calming/bump":{"fields":["surface","parallel_direction"],"geometry":["vertex","line"],"terms":["hump","speed","slow"],"tags":{"traffic_calming":"bump"},"name":"Speed Bump"},"traffic_calming/chicane":{"fields":["parallel_direction"],"geometry":["vertex","line"],"terms":["driveway link","speed","slow"],"tags":{"traffic_calming":"chicane"},"name":"Traffic Chicane"},"traffic_calming/choker":{"fields":["parallel_direction"],"geometry":["vertex","line"],"terms":["speed","slow"],"tags":{"traffic_calming":"choker"},"name":"Traffic Choker"},"traffic_calming/cushion":{"fields":["surface","parallel_direction"],"geometry":["vertex","line"],"terms":["bump","hump","speed","slow"],"tags":{"traffic_calming":"cushion"},"name":"Speed Cushion"},"traffic_calming/dip":{"fields":["surface","parallel_direction"],"geometry":["vertex","line"],"terms":["speed","slow"],"tags":{"traffic_calming":"dip"},"name":"Dip"},"traffic_calming/hump":{"fields":["surface","parallel_direction"],"geometry":["vertex","line"],"terms":["bump","speed","slow"],"tags":{"traffic_calming":"hump"},"name":"Speed Hump"},"traffic_calming/island":{"icon":"circle","geometry":["vertex"],"terms":["circle","roundabout","slow"],"tags":{"traffic_calming":"island"},"name":"Traffic Island"},"traffic_calming/rumble_strip":{"fields":["parallel_direction"],"geometry":["vertex","line"],"terms":["audible lines","sleeper lines","growlers"],"tags":{"traffic_calming":"rumble_strip"},"name":"Rumble Strip"},"traffic_calming/table":{"fields":["surface"],"geometry":["vertex","line"],"terms":["flat top","hump","speed","slow"],"tags":{"highway":"crossing","traffic_calming":"table"},"name":"Raised Pedestrian Crossing"},"type/multipolygon":{"geometry":["area","relation"],"tags":{"type":"multipolygon"},"removeTags":{},"name":"Multipolygon","icon":"multipolygon","searchable":false,"matchScore":0.1},"type/boundary":{"geometry":["relation"],"tags":{"type":"boundary"},"name":"Boundary","icon":"boundary","fields":["boundary"]},"type/boundary/administrative":{"name":"Administrative Boundary","geometry":["relation"],"tags":{"type":"boundary","boundary":"administrative"},"fields":["admin_level"],"icon":"boundary"},"type/restriction":{"geometry":["relation"],"tags":{"type":"restriction"},"name":"Restriction","icon":"restriction","fields":["restriction","except"]},"type/restriction/no_left_turn":{"name":"No Left Turn","geometry":["relation"],"tags":{"type":"restriction","restriction":"no_left_turn"},"fields":["except"],"icon":"restriction-no-left-turn"},"type/restriction/no_right_turn":{"name":"No Right Turn","geometry":["relation"],"tags":{"type":"restriction","restriction":"no_right_turn"},"fields":["except"],"icon":"restriction-no-right-turn"},"type/restriction/no_straight_on":{"name":"No Straight On","geometry":["relation"],"tags":{"type":"restriction","restriction":"no_straight_on"},"fields":["except"],"icon":"restriction-no-straight-on"},"type/restriction/no_u_turn":{"name":"No U-turn","geometry":["relation"],"tags":{"type":"restriction","restriction":"no_u_turn"},"fields":["except"],"icon":"restriction-no-u-turn"},"type/restriction/only_left_turn":{"name":"Left Turn Only","geometry":["relation"],"tags":{"type":"restriction","restriction":"only_left_turn"},"fields":["except"],"icon":"restriction-only-left-turn"},"type/restriction/only_right_turn":{"name":"Right Turn Only","geometry":["relation"],"tags":{"type":"restriction","restriction":"only_right_turn"},"fields":["except"],"icon":"restriction-only-right-turn"},"type/restriction/only_straight_on":{"name":"No Turns","geometry":["relation"],"tags":{"type":"restriction","restriction":"only_straight_on"},"fields":["except"],"icon":"restriction-only-straight-on"},"type/route_master":{"geometry":["relation"],"tags":{"type":"route_master"},"name":"Route Master","icon":"route-master","fields":["route_master","ref","operator","network"]},"type/route":{"geometry":["relation"],"tags":{"type":"route"},"name":"Route","icon":"route","fields":["route","ref","operator","network"]},"type/route/bicycle":{"geometry":["relation"],"tags":{"type":"route","route":"bicycle"},"name":"Cycle Route","icon":"route-bicycle","fields":["ref","network_bicycle","cycle_network"]},"type/route/bus":{"geometry":["relation"],"tags":{"type":"route","route":"bus"},"name":"Bus Route","icon":"route-bus","fields":["ref","operator","network"]},"type/route/detour":{"geometry":["relation"],"tags":{"type":"route","route":"detour"},"name":"Detour Route","icon":"route-detour","fields":["ref"]},"type/route/ferry":{"geometry":["relation"],"tags":{"type":"route","route":"ferry"},"name":"Ferry Route","icon":"route-ferry","fields":["ref","operator","network"]},"type/route/foot":{"geometry":["relation"],"tags":{"type":"route","route":"foot"},"name":"Foot Route","icon":"route-foot","fields":["ref","operator","network_foot"]},"type/route/hiking":{"geometry":["relation"],"tags":{"type":"route","route":"hiking"},"name":"Hiking Route","icon":"route-foot","fields":["ref","operator","network_foot"]},"type/route/horse":{"geometry":["relation"],"tags":{"type":"route","route":"horse"},"name":"Riding Route","icon":"route-horse","fields":["ref","operator","network_horse"]},"type/route/pipeline":{"geometry":["relation"],"tags":{"type":"route","route":"pipeline"},"name":"Pipeline Route","icon":"route-pipeline","fields":["ref","operator"]},"type/route/power":{"geometry":["relation"],"tags":{"type":"route","route":"power"},"name":"Power Route","icon":"route-power","fields":["ref","operator"]},"type/route/road":{"geometry":["relation"],"tags":{"type":"route","route":"road"},"name":"Road Route","icon":"route-road","fields":["ref","network_road"]},"type/route/train":{"geometry":["relation"],"tags":{"type":"route","route":"train"},"name":"Train Route","icon":"route-train","fields":["ref","operator","network"]},"type/route/tram":{"geometry":["relation"],"tags":{"type":"route","route":"tram"},"name":"Tram Route","icon":"route-tram","fields":["ref","operator","network"]},"type/site":{"geometry":["relation"],"tags":{"type":"site"},"name":"Site","icon":"relation","fields":["site"]},"vertex":{"name":"Other","tags":{},"geometry":["vertex"],"matchScore":0.1},"waterway/boatyard":{"icon":"harbor","fields":["operator"],"geometry":["area","vertex","point"],"tags":{"waterway":"boatyard"},"name":"Boatyard"},"waterway/canal":{"icon":"waterway-canal","fields":["width"],"geometry":["line"],"tags":{"waterway":"canal"},"name":"Canal"},"waterway/dam":{"icon":"dam","geometry":["point","vertex","line","area"],"tags":{"waterway":"dam"},"name":"Dam"},"waterway/ditch":{"icon":"waterway-ditch","fields":["tunnel"],"geometry":["line"],"tags":{"waterway":"ditch"},"name":"Ditch"},"waterway/dock":{"icon":"harbor","fields":["dock","operator"],"geometry":["area","vertex","point"],"terms":["boat","ship","vessel","marine"],"tags":{"waterway":"dock"},"name":"Wet Dock / Dry Dock"},"waterway/drain":{"icon":"waterway-stream","fields":["tunnel"],"geometry":["line"],"tags":{"waterway":"drain"},"name":"Drain"},"waterway/fuel":{"icon":"fuel","fields":["operator","address","opening_hours","fuel_multi"],"geometry":["point","area"],"terms":["petrol","gas","diesel","boat"],"tags":{"waterway":"fuel"},"name":"Marine Fuel Station"},"waterway/river":{"icon":"waterway-river","fields":["tunnel","width"],"geometry":["line"],"terms":["beck","branch","brook","course","creek","estuary","rill","rivulet","run","runnel","stream","tributary","watercourse"],"tags":{"waterway":"river"},"name":"River"},"waterway/riverbank":{"icon":"water","geometry":["area"],"tags":{"waterway":"riverbank"},"name":"Riverbank"},"waterway/sanitary_dump_station":{"fields":["operator","access_toilets","fee","water_point"],"geometry":["point","vertex","area"],"terms":["Boat","Watercraft","Sanitary","Dump Station","Pumpout","Pump out","Elsan","CDP","CTDP","Chemical Toilet"],"tags":{"waterway":"sanitary_dump_station"},"name":"Marine Toilet Disposal"},"waterway/stream":{"icon":"waterway-stream","fields":["tunnel","width"],"geometry":["line"],"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"],"tags":{"waterway":"stream"},"name":"Stream"},"waterway/water_point":{"icon":"water","geometry":["area","vertex","point"],"tags":{"waterway":"water_point"},"name":"Marine Drinking Water"},"waterway/weir":{"icon":"dam","geometry":["vertex","line"],"tags":{"waterway":"weir"},"name":"Weir"},"amenity/fuel/76":{"tags":{"name":"76","amenity":"fuel"},"name":"76","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Neste":{"tags":{"name":"Neste","amenity":"fuel"},"name":"Neste","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/BP":{"tags":{"name":"BP","amenity":"fuel"},"name":"BP","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Shell":{"tags":{"name":"Shell","amenity":"fuel"},"name":"Shell","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Agip":{"tags":{"name":"Agip","amenity":"fuel"},"name":"Agip","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Migrol":{"tags":{"name":"Migrol","amenity":"fuel"},"name":"Migrol","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Avia":{"tags":{"name":"Avia","amenity":"fuel"},"name":"Avia","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Texaco":{"tags":{"name":"Texaco","amenity":"fuel"},"name":"Texaco","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Total":{"tags":{"name":"Total","amenity":"fuel"},"name":"Total","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Statoil":{"tags":{"name":"Statoil","amenity":"fuel"},"name":"Statoil","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Esso":{"tags":{"name":"Esso","amenity":"fuel"},"name":"Esso","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Jet":{"tags":{"name":"Jet","amenity":"fuel"},"name":"Jet","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Avanti":{"tags":{"name":"Avanti","amenity":"fuel"},"name":"Avanti","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/OMV":{"tags":{"name":"OMV","amenity":"fuel"},"name":"OMV","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Aral":{"tags":{"name":"Aral","amenity":"fuel"},"name":"Aral","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/JET":{"tags":{"name":"JET","amenity":"fuel"},"name":"JET","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/United":{"tags":{"name":"United","amenity":"fuel"},"name":"United","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Mobil":{"tags":{"name":"Mobil","amenity":"fuel"},"name":"Mobil","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Caltex":{"tags":{"name":"Caltex","amenity":"fuel"},"name":"Caltex","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Sunoco":{"tags":{"name":"Sunoco","amenity":"fuel"},"name":"Sunoco","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Q8":{"tags":{"name":"Q8","amenity":"fuel"},"name":"Q8","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/ARAL":{"tags":{"name":"ARAL","amenity":"fuel"},"name":"ARAL","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/CEPSA":{"tags":{"name":"CEPSA","amenity":"fuel"},"name":"CEPSA","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/BFT":{"tags":{"name":"BFT","amenity":"fuel"},"name":"BFT","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Petron":{"tags":{"name":"Petron","amenity":"fuel"},"name":"Petron","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Total Access":{"tags":{"name":"Total Access","amenity":"fuel"},"name":"Total Access","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Elf":{"tags":{"name":"Elf","amenity":"fuel"},"name":"Elf","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Station Service E. Leclerc":{"tags":{"name":"Station Service E. Leclerc","amenity":"fuel"},"name":"Station Service E. Leclerc","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Shell Express":{"tags":{"name":"Shell Express","amenity":"fuel"},"name":"Shell Express","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Hess":{"tags":{"name":"Hess","amenity":"fuel"},"name":"Hess","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Flying V":{"tags":{"name":"Flying V","amenity":"fuel"},"name":"Flying V","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/bft":{"tags":{"name":"bft","amenity":"fuel"},"name":"bft","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Gulf":{"tags":{"name":"Gulf","amenity":"fuel"},"name":"Gulf","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/PTT":{"tags":{"name":"PTT","amenity":"fuel"},"name":"PTT","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/St1":{"tags":{"name":"St1","amenity":"fuel"},"name":"St1","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Teboil":{"tags":{"name":"Teboil","amenity":"fuel"},"name":"Teboil","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/HEM":{"tags":{"name":"HEM","amenity":"fuel"},"name":"HEM","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/GALP":{"tags":{"name":"GALP","amenity":"fuel"},"name":"GALP","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/OK":{"tags":{"name":"OK","amenity":"fuel"},"name":"OK","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/ÖMV":{"tags":{"name":"ÖMV","amenity":"fuel"},"name":"ÖMV","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Tinq":{"tags":{"name":"Tinq","amenity":"fuel"},"name":"Tinq","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/OKQ8":{"tags":{"name":"OKQ8","amenity":"fuel"},"name":"OKQ8","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Repsol":{"tags":{"name":"Repsol","amenity":"fuel"},"name":"Repsol","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Westfalen":{"tags":{"name":"Westfalen","amenity":"fuel"},"name":"Westfalen","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Esso Express":{"tags":{"name":"Esso Express","amenity":"fuel"},"name":"Esso Express","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Tamoil":{"tags":{"name":"Tamoil","amenity":"fuel"},"name":"Tamoil","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Engen":{"tags":{"name":"Engen","amenity":"fuel"},"name":"Engen","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Sasol":{"tags":{"name":"Sasol","amenity":"fuel"},"name":"Sasol","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Topaz":{"tags":{"name":"Topaz","amenity":"fuel"},"name":"Topaz","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/LPG":{"tags":{"name":"LPG","amenity":"fuel"},"name":"LPG","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Orlen":{"tags":{"name":"Orlen","amenity":"fuel"},"name":"Orlen","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Oilibya":{"tags":{"name":"Oilibya","amenity":"fuel"},"name":"Oilibya","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Tango":{"tags":{"name":"Tango","amenity":"fuel"},"name":"Tango","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Star":{"tags":{"name":"Star","amenity":"fuel"},"name":"Star","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Петрол":{"tags":{"name":"Петрол","amenity":"fuel"},"name":"Петрол","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Cepsa":{"tags":{"name":"Cepsa","amenity":"fuel"},"name":"Cepsa","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/OIL!":{"tags":{"name":"OIL!","amenity":"fuel"},"name":"OIL!","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Ultramar":{"tags":{"name":"Ultramar","amenity":"fuel"},"name":"Ultramar","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Irving":{"tags":{"name":"Irving","amenity":"fuel"},"name":"Irving","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Lukoil":{"tags":{"name":"Lukoil","amenity":"fuel"},"name":"Lukoil","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Petro-Canada":{"tags":{"name":"Petro-Canada","amenity":"fuel"},"name":"Petro-Canada","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Agrola":{"tags":{"name":"Agrola","amenity":"fuel"},"name":"Agrola","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Husky":{"tags":{"name":"Husky","amenity":"fuel"},"name":"Husky","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Slovnaft":{"tags":{"name":"Slovnaft","amenity":"fuel"},"name":"Slovnaft","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Sheetz":{"tags":{"name":"Sheetz","amenity":"fuel"},"name":"Sheetz","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Mol":{"tags":{"name":"Mol","amenity":"fuel"},"name":"Mol","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Petronas":{"tags":{"name":"Petronas","amenity":"fuel"},"name":"Petronas","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Газпромнефть":{"tags":{"name":"Газпромнефть","amenity":"fuel"},"name":"Газпромнефть","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Лукойл":{"tags":{"name":"Лукойл","amenity":"fuel"},"name":"Лукойл","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Elan":{"tags":{"name":"Elan","amenity":"fuel"},"name":"Elan","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Роснефть":{"tags":{"name":"Роснефть","amenity":"fuel"},"name":"Роснефть","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Turmöl":{"tags":{"name":"Turmöl","amenity":"fuel"},"name":"Turmöl","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Neste A24":{"tags":{"name":"Neste A24","amenity":"fuel"},"name":"Neste A24","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Marathon":{"tags":{"name":"Marathon","amenity":"fuel"},"name":"Marathon","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Valero":{"tags":{"name":"Valero","amenity":"fuel"},"name":"Valero","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Eni":{"tags":{"name":"Eni","amenity":"fuel"},"name":"Eni","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Chevron":{"tags":{"name":"Chevron","amenity":"fuel"},"name":"Chevron","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/ТНК":{"tags":{"name":"ТНК","amenity":"fuel"},"name":"ТНК","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/REPSOL":{"tags":{"name":"REPSOL","amenity":"fuel"},"name":"REPSOL","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/MOL":{"tags":{"name":"MOL","amenity":"fuel"},"name":"MOL","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Bliska":{"tags":{"name":"Bliska","amenity":"fuel"},"name":"Bliska","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Api":{"tags":{"name":"Api","amenity":"fuel"},"name":"Api","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Arco":{"tags":{"name":"Arco","amenity":"fuel"},"name":"Arco","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Pemex":{"tags":{"name":"Pemex","amenity":"fuel"},"name":"Pemex","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Exxon":{"tags":{"name":"Exxon","amenity":"fuel"},"name":"Exxon","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Coles Express":{"tags":{"name":"Coles Express","amenity":"fuel"},"name":"Coles Express","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Petrom":{"tags":{"name":"Petrom","amenity":"fuel"},"name":"Petrom","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/PETRONOR":{"tags":{"name":"PETRONOR","amenity":"fuel"},"name":"PETRONOR","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Rompetrol":{"tags":{"name":"Rompetrol","amenity":"fuel"},"name":"Rompetrol","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Lotos":{"tags":{"name":"Lotos","amenity":"fuel"},"name":"Lotos","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/ОМВ":{"tags":{"name":"ОМВ","amenity":"fuel"},"name":"ОМВ","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/BR":{"tags":{"name":"BR","amenity":"fuel"},"name":"BR","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Copec":{"tags":{"name":"Copec","amenity":"fuel"},"name":"Copec","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Petrobras":{"tags":{"name":"Petrobras","amenity":"fuel"},"name":"Petrobras","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Liberty":{"tags":{"name":"Liberty","amenity":"fuel"},"name":"Liberty","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/IP":{"tags":{"name":"IP","amenity":"fuel"},"name":"IP","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Erg":{"tags":{"name":"Erg","amenity":"fuel"},"name":"Erg","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Eneos":{"tags":{"name":"Eneos","amenity":"fuel"},"name":"Eneos","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Citgo":{"tags":{"name":"Citgo","amenity":"fuel"},"name":"Citgo","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Metano":{"tags":{"name":"Metano","amenity":"fuel"},"name":"Metano","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Сургутнефтегаз":{"tags":{"name":"Сургутнефтегаз","amenity":"fuel"},"name":"Сургутнефтегаз","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/EKO":{"tags":{"name":"EKO","amenity":"fuel"},"name":"EKO","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Eko":{"tags":{"name":"Eko","amenity":"fuel"},"name":"Eko","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Indipend.":{"tags":{"name":"Indipend.","amenity":"fuel"},"name":"Indipend.","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/IES":{"tags":{"name":"IES","amenity":"fuel"},"name":"IES","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/TotalErg":{"tags":{"name":"TotalErg","amenity":"fuel"},"name":"TotalErg","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Cenex":{"tags":{"name":"Cenex","amenity":"fuel"},"name":"Cenex","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/ПТК":{"tags":{"name":"ПТК","amenity":"fuel"},"name":"ПТК","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/HP":{"tags":{"name":"HP","amenity":"fuel"},"name":"HP","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Phillips 66":{"tags":{"name":"Phillips 66","amenity":"fuel"},"name":"Phillips 66","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/CARREFOUR":{"tags":{"name":"CARREFOUR","amenity":"fuel"},"name":"CARREFOUR","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/ERG":{"tags":{"name":"ERG","amenity":"fuel"},"name":"ERG","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Speedway":{"tags":{"name":"Speedway","amenity":"fuel"},"name":"Speedway","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Benzina":{"tags":{"name":"Benzina","amenity":"fuel"},"name":"Benzina","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Татнефть":{"tags":{"name":"Татнефть","amenity":"fuel"},"name":"Татнефть","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Terpel":{"tags":{"name":"Terpel","amenity":"fuel"},"name":"Terpel","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/WOG":{"tags":{"name":"WOG","amenity":"fuel"},"name":"WOG","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Seaoil":{"tags":{"name":"Seaoil","amenity":"fuel"},"name":"Seaoil","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/АЗС":{"tags":{"name":"АЗС","amenity":"fuel"},"name":"АЗС","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Kwik Trip":{"tags":{"name":"Kwik Trip","amenity":"fuel"},"name":"Kwik Trip","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Pertamina":{"tags":{"name":"Pertamina","amenity":"fuel"},"name":"Pertamina","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/COSMO":{"tags":{"name":"COSMO","amenity":"fuel"},"name":"COSMO","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Z":{"tags":{"name":"Z","amenity":"fuel"},"name":"Z","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Indian Oil":{"tags":{"name":"Indian Oil","amenity":"fuel"},"name":"Indian Oil","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/АГЗС":{"tags":{"name":"АГЗС","amenity":"fuel"},"name":"АГЗС","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/INA":{"tags":{"name":"INA","amenity":"fuel"},"name":"INA","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/JOMO":{"tags":{"name":"JOMO","amenity":"fuel"},"name":"JOMO","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Holiday":{"tags":{"name":"Holiday","amenity":"fuel"},"name":"Holiday","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/YPF":{"tags":{"name":"YPF","amenity":"fuel"},"name":"YPF","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/IDEMITSU":{"tags":{"name":"IDEMITSU","amenity":"fuel"},"name":"IDEMITSU","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/ENEOS":{"tags":{"name":"ENEOS","amenity":"fuel"},"name":"ENEOS","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Bharat Petroleum":{"tags":{"name":"Bharat Petroleum","amenity":"fuel"},"name":"Bharat Petroleum","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/CAMPSA":{"tags":{"name":"CAMPSA","amenity":"fuel"},"name":"CAMPSA","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Casey's General Store":{"tags":{"name":"Casey's General Store","amenity":"fuel"},"name":"Casey's General Store","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Башнефть":{"tags":{"name":"Башнефть","amenity":"fuel"},"name":"Башнефть","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Kangaroo":{"tags":{"name":"Kangaroo","amenity":"fuel"},"name":"Kangaroo","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/コスモ石油 (COSMO)":{"tags":{"name":"コスモ石油 (COSMO)","amenity":"fuel"},"name":"コスモ石油 (COSMO)","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/MEROIL":{"tags":{"name":"MEROIL","amenity":"fuel"},"name":"MEROIL","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/1-2-3":{"tags":{"name":"1-2-3","amenity":"fuel"},"name":"1-2-3","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/出光":{"tags":{"name":"出光","name:en":"IDEMITSU","amenity":"fuel"},"name":"出光","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/НК Альянс":{"tags":{"name":"НК Альянс","amenity":"fuel"},"name":"НК Альянс","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Sinclair":{"tags":{"name":"Sinclair","amenity":"fuel"},"name":"Sinclair","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Conoco":{"tags":{"name":"Conoco","amenity":"fuel"},"name":"Conoco","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/SPBU":{"tags":{"name":"SPBU","amenity":"fuel"},"name":"SPBU","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Макпетрол":{"tags":{"name":"Макпетрол","amenity":"fuel"},"name":"Макпетрол","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Posto Ipiranga":{"tags":{"name":"Posto Ipiranga","amenity":"fuel"},"name":"Posto Ipiranga","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Posto Shell":{"tags":{"name":"Posto Shell","amenity":"fuel"},"name":"Posto Shell","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Phoenix":{"tags":{"name":"Phoenix","amenity":"fuel"},"name":"Phoenix","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Ipiranga":{"tags":{"name":"Ipiranga","amenity":"fuel"},"name":"Ipiranga","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/OKKO":{"tags":{"name":"OKKO","amenity":"fuel"},"name":"OKKO","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/ОККО":{"tags":{"name":"ОККО","amenity":"fuel"},"name":"ОККО","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/บางจาก":{"tags":{"name":"บางจาก","amenity":"fuel"},"name":"บางจาก","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/QuikTrip":{"tags":{"name":"QuikTrip","amenity":"fuel"},"name":"QuikTrip","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Posto BR":{"tags":{"name":"Posto BR","amenity":"fuel"},"name":"Posto BR","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/ป ต ท":{"tags":{"name":"ป ต ท","amenity":"fuel"},"name":"ป ต ท","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/ปตท":{"tags":{"name":"ปตท","amenity":"fuel"},"name":"ปตท","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/ANP":{"tags":{"name":"ANP","amenity":"fuel"},"name":"ANP","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Kum & Go":{"tags":{"name":"Kum & Go","amenity":"fuel"},"name":"Kum & Go","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Petrolimex":{"tags":{"name":"Petrolimex","amenity":"fuel"},"name":"Petrolimex","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Sokimex":{"tags":{"name":"Sokimex","amenity":"fuel"},"name":"Sokimex","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Tela":{"tags":{"name":"Tela","amenity":"fuel"},"name":"Tela","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Posto":{"tags":{"name":"Posto","amenity":"fuel"},"name":"Posto","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Укрнафта":{"tags":{"name":"Укрнафта","amenity":"fuel"},"name":"Укрнафта","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Татнефтепродукт":{"tags":{"name":"Татнефтепродукт","amenity":"fuel"},"name":"Татнефтепродукт","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Afriquia":{"tags":{"name":"Afriquia","amenity":"fuel"},"name":"Afriquia","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/Murphy USA":{"tags":{"name":"Murphy USA","amenity":"fuel"},"name":"Murphy USA","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/昭和シェル (Showa-shell)":{"tags":{"name":"昭和シェル (Showa-shell)","amenity":"fuel"},"name":"昭和シェル (Showa-shell)","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/エネオス":{"tags":{"name":"エネオス","amenity":"fuel"},"name":"エネオス","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/fuel/CNG":{"tags":{"name":"CNG","amenity":"fuel"},"name":"CNG","icon":"fuel","geometry":["point","area"],"fields":["operator","address","opening_hours","fuel_multi"],"suggestion":true},"amenity/pub/Kings Arms":{"tags":{"name":"Kings Arms","amenity":"pub"},"name":"Kings Arms","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Ship":{"tags":{"name":"The Ship","amenity":"pub"},"name":"The Ship","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The White Horse":{"tags":{"name":"The White Horse","amenity":"pub"},"name":"The White Horse","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The White Hart":{"tags":{"name":"The White Hart","amenity":"pub"},"name":"The White Hart","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/Royal Oak":{"tags":{"name":"Royal Oak","amenity":"pub"},"name":"Royal Oak","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Red Lion":{"tags":{"name":"The Red Lion","amenity":"pub"},"name":"The Red Lion","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Kings Arms":{"tags":{"name":"The Kings Arms","amenity":"pub"},"name":"The Kings Arms","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Star":{"tags":{"name":"The Star","amenity":"pub"},"name":"The Star","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Anchor":{"tags":{"name":"The Anchor","amenity":"pub"},"name":"The Anchor","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Cross Keys":{"tags":{"name":"The Cross Keys","amenity":"pub"},"name":"The Cross Keys","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Wheatsheaf":{"tags":{"name":"The Wheatsheaf","amenity":"pub"},"name":"The Wheatsheaf","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Crown Inn":{"tags":{"name":"The Crown Inn","amenity":"pub"},"name":"The Crown Inn","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Kings Head":{"tags":{"name":"The Kings Head","amenity":"pub"},"name":"The Kings Head","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Castle":{"tags":{"name":"The Castle","amenity":"pub"},"name":"The Castle","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Railway":{"tags":{"name":"The Railway","amenity":"pub"},"name":"The Railway","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The White Lion":{"tags":{"name":"The White Lion","amenity":"pub"},"name":"The White Lion","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Bell":{"tags":{"name":"The Bell","amenity":"pub"},"name":"The Bell","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Bull":{"tags":{"name":"The Bull","amenity":"pub"},"name":"The Bull","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Plough":{"tags":{"name":"The Plough","amenity":"pub"},"name":"The Plough","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The George":{"tags":{"name":"The George","amenity":"pub"},"name":"The George","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Royal Oak":{"tags":{"name":"The Royal Oak","amenity":"pub"},"name":"The Royal Oak","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Fox":{"tags":{"name":"The Fox","amenity":"pub"},"name":"The Fox","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/Prince of Wales":{"tags":{"name":"Prince of Wales","amenity":"pub"},"name":"Prince of Wales","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Rising Sun":{"tags":{"name":"The Rising Sun","amenity":"pub"},"name":"The Rising Sun","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Prince of Wales":{"tags":{"name":"The Prince of Wales","amenity":"pub"},"name":"The Prince of Wales","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Crown":{"tags":{"name":"The Crown","amenity":"pub"},"name":"The Crown","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Chequers":{"tags":{"name":"The Chequers","amenity":"pub"},"name":"The Chequers","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Swan":{"tags":{"name":"The Swan","amenity":"pub"},"name":"The Swan","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/Rose and Crown":{"tags":{"name":"Rose and Crown","amenity":"pub"},"name":"Rose and Crown","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Victoria":{"tags":{"name":"The Victoria","amenity":"pub"},"name":"The Victoria","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/New Inn":{"tags":{"name":"New Inn","amenity":"pub"},"name":"New Inn","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/Royal Hotel":{"tags":{"name":"Royal Hotel","amenity":"pub"},"name":"Royal Hotel","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/Red Lion":{"tags":{"name":"Red Lion","amenity":"pub"},"name":"Red Lion","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/Cross Keys":{"tags":{"name":"Cross Keys","amenity":"pub"},"name":"Cross Keys","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Greyhound":{"tags":{"name":"The Greyhound","amenity":"pub"},"name":"The Greyhound","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Black Horse":{"tags":{"name":"The Black Horse","amenity":"pub"},"name":"The Black Horse","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The New Inn":{"tags":{"name":"The New Inn","amenity":"pub"},"name":"The New Inn","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/Kings Head":{"tags":{"name":"Kings Head","amenity":"pub"},"name":"Kings Head","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Albion":{"tags":{"name":"The Albion","amenity":"pub"},"name":"The Albion","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Angel":{"tags":{"name":"The Angel","amenity":"pub"},"name":"The Angel","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Queens Head":{"tags":{"name":"The Queens Head","amenity":"pub"},"name":"The Queens Head","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/The Ship Inn":{"tags":{"name":"The Ship Inn","amenity":"pub"},"name":"The Ship Inn","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/Rose & Crown":{"tags":{"name":"Rose & Crown","amenity":"pub"},"name":"Rose & Crown","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/Queens Head":{"tags":{"name":"Queens Head","amenity":"pub"},"name":"Queens Head","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/pub/Irish Pub":{"tags":{"name":"Irish Pub","amenity":"pub"},"name":"Irish Pub","icon":"beer","geometry":["point","area"],"fields":["address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/fast_food/Quick":{"tags":{"name":"Quick","amenity":"fast_food"},"name":"Quick","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/McDonald's":{"tags":{"name":"McDonald's","cuisine":"burger","amenity":"fast_food"},"name":"McDonald's","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Subway":{"tags":{"name":"Subway","cuisine":"sandwich","amenity":"fast_food"},"name":"Subway","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Burger King":{"tags":{"name":"Burger King","cuisine":"burger","amenity":"fast_food"},"name":"Burger King","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Ali Baba":{"tags":{"name":"Ali Baba","amenity":"fast_food"},"name":"Ali Baba","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Hungry Jacks":{"tags":{"name":"Hungry Jacks","cuisine":"burger","amenity":"fast_food"},"name":"Hungry Jacks","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Red Rooster":{"tags":{"name":"Red Rooster","amenity":"fast_food"},"name":"Red Rooster","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/KFC":{"tags":{"name":"KFC","cuisine":"chicken","amenity":"fast_food"},"name":"KFC","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Domino's Pizza":{"tags":{"name":"Domino's Pizza","cuisine":"pizza","amenity":"fast_food"},"name":"Domino's Pizza","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Chowking":{"tags":{"name":"Chowking","amenity":"fast_food"},"name":"Chowking","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Jollibee":{"tags":{"name":"Jollibee","amenity":"fast_food"},"name":"Jollibee","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Hesburger":{"tags":{"name":"Hesburger","amenity":"fast_food"},"name":"Hesburger","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/肯德基":{"tags":{"name":"肯德基","amenity":"fast_food"},"name":"肯德基","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Wendy's":{"tags":{"name":"Wendy's","cuisine":"burger","amenity":"fast_food"},"name":"Wendy's","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Tim Hortons":{"tags":{"name":"Tim Hortons","amenity":"fast_food"},"name":"Tim Hortons","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Steers":{"tags":{"name":"Steers","amenity":"fast_food"},"name":"Steers","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Hardee's":{"tags":{"name":"Hardee's","cuisine":"burger","amenity":"fast_food"},"name":"Hardee's","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Arby's":{"tags":{"name":"Arby's","amenity":"fast_food"},"name":"Arby's","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/A&W":{"tags":{"name":"A&W","amenity":"fast_food"},"name":"A&W","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Dairy Queen":{"tags":{"name":"Dairy Queen","amenity":"fast_food"},"name":"Dairy Queen","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Hallo Pizza":{"tags":{"name":"Hallo Pizza","amenity":"fast_food"},"name":"Hallo Pizza","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Fish & Chips":{"tags":{"name":"Fish & Chips","amenity":"fast_food"},"name":"Fish & Chips","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Harvey's":{"tags":{"name":"Harvey's","amenity":"fast_food"},"name":"Harvey's","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/麥當勞":{"tags":{"name":"麥當勞","amenity":"fast_food"},"name":"麥當勞","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Pizza Pizza":{"tags":{"name":"Pizza Pizza","amenity":"fast_food"},"name":"Pizza Pizza","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Kotipizza":{"tags":{"name":"Kotipizza","amenity":"fast_food"},"name":"Kotipizza","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Jack in the Box":{"tags":{"name":"Jack in the Box","cuisine":"burger","amenity":"fast_food"},"name":"Jack in the Box","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Istanbul":{"tags":{"name":"Istanbul","amenity":"fast_food"},"name":"Istanbul","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Kochlöffel":{"tags":{"name":"Kochlöffel","amenity":"fast_food"},"name":"Kochlöffel","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Döner":{"tags":{"name":"Döner","amenity":"fast_food"},"name":"Döner","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Telepizza":{"tags":{"name":"Telepizza","amenity":"fast_food"},"name":"Telepizza","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Sibylla":{"tags":{"name":"Sibylla","amenity":"fast_food"},"name":"Sibylla","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Carl's Jr.":{"tags":{"name":"Carl's Jr.","cuisine":"burger","amenity":"fast_food"},"name":"Carl's Jr.","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Quiznos":{"tags":{"name":"Quiznos","cuisine":"sandwich","amenity":"fast_food"},"name":"Quiznos","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Wimpy":{"tags":{"name":"Wimpy","amenity":"fast_food"},"name":"Wimpy","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Sonic":{"tags":{"name":"Sonic","cuisine":"burger","amenity":"fast_food"},"name":"Sonic","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Taco Bell":{"tags":{"name":"Taco Bell","cuisine":"mexican","amenity":"fast_food"},"name":"Taco Bell","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Pizza Nova":{"tags":{"name":"Pizza Nova","amenity":"fast_food"},"name":"Pizza Nova","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Papa John's":{"tags":{"name":"Papa John's","cuisine":"pizza","amenity":"fast_food"},"name":"Papa John's","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Nordsee":{"tags":{"name":"Nordsee","amenity":"fast_food"},"name":"Nordsee","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Mr. Sub":{"tags":{"name":"Mr. Sub","amenity":"fast_food"},"name":"Mr. Sub","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Макдоналдс":{"tags":{"name":"Макдоналдс","name:en":"McDonald's","amenity":"fast_food"},"name":"Макдоналдс","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Asia Imbiss":{"tags":{"name":"Asia Imbiss","amenity":"fast_food"},"name":"Asia Imbiss","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Chipotle":{"tags":{"name":"Chipotle","cuisine":"mexican","amenity":"fast_food"},"name":"Chipotle","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/マクドナルド":{"tags":{"name":"マクドナルド","name:en":"McDonald's","cuisine":"burger","amenity":"fast_food"},"name":"マクドナルド","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/In-N-Out Burger":{"tags":{"name":"In-N-Out Burger","amenity":"fast_food"},"name":"In-N-Out Burger","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Jimmy John's":{"tags":{"name":"Jimmy John's","amenity":"fast_food"},"name":"Jimmy John's","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Jamba Juice":{"tags":{"name":"Jamba Juice","amenity":"fast_food"},"name":"Jamba Juice","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Робин Сдобин":{"tags":{"name":"Робин Сдобин","amenity":"fast_food"},"name":"Робин Сдобин","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Baskin Robbins":{"tags":{"name":"Baskin Robbins","amenity":"fast_food"},"name":"Baskin Robbins","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/ケンタッキーフライドチキン":{"tags":{"name":"ケンタッキーフライドチキン","name:en":"KFC","cuisine":"chicken","amenity":"fast_food"},"name":"ケンタッキーフライドチキン","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/吉野家":{"tags":{"name":"吉野家","amenity":"fast_food"},"name":"吉野家","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Taco Time":{"tags":{"name":"Taco Time","amenity":"fast_food"},"name":"Taco Time","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/松屋":{"tags":{"name":"松屋","name:en":"Matsuya","amenity":"fast_food"},"name":"松屋","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Little Caesars":{"tags":{"name":"Little Caesars","amenity":"fast_food"},"name":"Little Caesars","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/El Pollo Loco":{"tags":{"name":"El Pollo Loco","amenity":"fast_food"},"name":"El Pollo Loco","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Del Taco":{"tags":{"name":"Del Taco","amenity":"fast_food"},"name":"Del Taco","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/White Castle":{"tags":{"name":"White Castle","amenity":"fast_food"},"name":"White Castle","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Boston Market":{"tags":{"name":"Boston Market","amenity":"fast_food"},"name":"Boston Market","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Chick-fil-A":{"tags":{"name":"Chick-fil-A","cuisine":"chicken","amenity":"fast_food"},"name":"Chick-fil-A","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Panda Express":{"tags":{"name":"Panda Express","cuisine":"chinese","amenity":"fast_food"},"name":"Panda Express","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Whataburger":{"tags":{"name":"Whataburger","amenity":"fast_food"},"name":"Whataburger","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Taco John's":{"tags":{"name":"Taco John's","amenity":"fast_food"},"name":"Taco John's","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Теремок":{"tags":{"name":"Теремок","amenity":"fast_food"},"name":"Теремок","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Culver's":{"tags":{"name":"Culver's","amenity":"fast_food"},"name":"Culver's","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Five Guys":{"tags":{"name":"Five Guys","amenity":"fast_food"},"name":"Five Guys","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Church's Chicken":{"tags":{"name":"Church's Chicken","amenity":"fast_food"},"name":"Church's Chicken","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Popeye's":{"tags":{"name":"Popeye's","cuisine":"chicken","amenity":"fast_food"},"name":"Popeye's","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Long John Silver's":{"tags":{"name":"Long John Silver's","amenity":"fast_food"},"name":"Long John Silver's","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Pollo Campero":{"tags":{"name":"Pollo Campero","amenity":"fast_food"},"name":"Pollo Campero","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Zaxby's":{"tags":{"name":"Zaxby's","amenity":"fast_food"},"name":"Zaxby's","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/すき家":{"tags":{"name":"すき家","name:en":"SUKIYA","amenity":"fast_food"},"name":"すき家","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/モスバーガー":{"tags":{"name":"モスバーガー","name:en":"MOS BURGER","amenity":"fast_food"},"name":"モスバーガー","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/Русский Аппетит":{"tags":{"name":"Русский Аппетит","amenity":"fast_food"},"name":"Русский Аппетит","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/fast_food/なか卯":{"tags":{"name":"なか卯","amenity":"fast_food"},"name":"なか卯","icon":"fast-food","geometry":["point","area"],"fields":["cuisine","operator","address","building_area","opening_hours","takeaway","delivery","drive_through","smoking"],"suggestion":true},"amenity/restaurant/Pizza Hut":{"tags":{"name":"Pizza Hut","cuisine":"pizza","amenity":"restaurant"},"name":"Pizza Hut","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Little Chef":{"tags":{"name":"Little Chef","amenity":"restaurant"},"name":"Little Chef","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Adler":{"tags":{"name":"Adler","amenity":"restaurant"},"name":"Adler","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Zur Krone":{"tags":{"name":"Zur Krone","amenity":"restaurant"},"name":"Zur Krone","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Deutsches Haus":{"tags":{"name":"Deutsches Haus","amenity":"restaurant"},"name":"Deutsches Haus","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Krone":{"tags":{"name":"Krone","amenity":"restaurant"},"name":"Krone","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Akropolis":{"tags":{"name":"Akropolis","amenity":"restaurant"},"name":"Akropolis","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Schützenhaus":{"tags":{"name":"Schützenhaus","amenity":"restaurant"},"name":"Schützenhaus","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Kreuz":{"tags":{"name":"Kreuz","amenity":"restaurant"},"name":"Kreuz","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Waldschänke":{"tags":{"name":"Waldschänke","amenity":"restaurant"},"name":"Waldschänke","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/La Piazza":{"tags":{"name":"La Piazza","amenity":"restaurant"},"name":"La Piazza","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Lamm":{"tags":{"name":"Lamm","amenity":"restaurant"},"name":"Lamm","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Zur Sonne":{"tags":{"name":"Zur Sonne","amenity":"restaurant"},"name":"Zur Sonne","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Zur Linde":{"tags":{"name":"Zur Linde","amenity":"restaurant"},"name":"Zur Linde","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Poseidon":{"tags":{"name":"Poseidon","amenity":"restaurant"},"name":"Poseidon","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Shanghai":{"tags":{"name":"Shanghai","amenity":"restaurant"},"name":"Shanghai","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Red Lobster":{"tags":{"name":"Red Lobster","amenity":"restaurant"},"name":"Red Lobster","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Zum Löwen":{"tags":{"name":"Zum Löwen","amenity":"restaurant"},"name":"Zum Löwen","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Swiss Chalet":{"tags":{"name":"Swiss Chalet","amenity":"restaurant"},"name":"Swiss Chalet","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Olympia":{"tags":{"name":"Olympia","amenity":"restaurant"},"name":"Olympia","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Wagamama":{"tags":{"name":"Wagamama","amenity":"restaurant"},"name":"Wagamama","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Frankie & Benny's":{"tags":{"name":"Frankie & Benny's","amenity":"restaurant"},"name":"Frankie & Benny's","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Hooters":{"tags":{"name":"Hooters","amenity":"restaurant"},"name":"Hooters","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Sternen":{"tags":{"name":"Sternen","amenity":"restaurant"},"name":"Sternen","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Hirschen":{"tags":{"name":"Hirschen","amenity":"restaurant"},"name":"Hirschen","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Denny's":{"tags":{"name":"Denny's","amenity":"restaurant"},"name":"Denny's","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Athen":{"tags":{"name":"Athen","amenity":"restaurant"},"name":"Athen","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Sonne":{"tags":{"name":"Sonne","amenity":"restaurant"},"name":"Sonne","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Hirsch":{"tags":{"name":"Hirsch","amenity":"restaurant"},"name":"Hirsch","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Ratskeller":{"tags":{"name":"Ratskeller","amenity":"restaurant"},"name":"Ratskeller","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/La Cantina":{"tags":{"name":"La Cantina","amenity":"restaurant"},"name":"La Cantina","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Gasthaus Krone":{"tags":{"name":"Gasthaus Krone","amenity":"restaurant"},"name":"Gasthaus Krone","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/El Greco":{"tags":{"name":"El Greco","amenity":"restaurant"},"name":"El Greco","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Gasthof zur Post":{"tags":{"name":"Gasthof zur Post","amenity":"restaurant"},"name":"Gasthof zur Post","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Nando's":{"tags":{"name":"Nando's","amenity":"restaurant"},"name":"Nando's","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Löwen":{"tags":{"name":"Löwen","amenity":"restaurant"},"name":"Löwen","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/La Pataterie":{"tags":{"name":"La Pataterie","amenity":"restaurant"},"name":"La Pataterie","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Bella Napoli":{"tags":{"name":"Bella Napoli","amenity":"restaurant"},"name":"Bella Napoli","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Pizza Express":{"tags":{"name":"Pizza Express","amenity":"restaurant"},"name":"Pizza Express","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Mandarin":{"tags":{"name":"Mandarin","amenity":"restaurant"},"name":"Mandarin","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Hong Kong":{"tags":{"name":"Hong Kong","amenity":"restaurant"},"name":"Hong Kong","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Zizzi":{"tags":{"name":"Zizzi","amenity":"restaurant"},"name":"Zizzi","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Cracker Barrel":{"tags":{"name":"Cracker Barrel","amenity":"restaurant"},"name":"Cracker Barrel","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Rhodos":{"tags":{"name":"Rhodos","amenity":"restaurant"},"name":"Rhodos","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Lindenhof":{"tags":{"name":"Lindenhof","amenity":"restaurant"},"name":"Lindenhof","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Milano":{"tags":{"name":"Milano","amenity":"restaurant"},"name":"Milano","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Dolce Vita":{"tags":{"name":"Dolce Vita","amenity":"restaurant"},"name":"Dolce Vita","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Kirchenwirt":{"tags":{"name":"Kirchenwirt","amenity":"restaurant"},"name":"Kirchenwirt","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Kantine":{"tags":{"name":"Kantine","amenity":"restaurant"},"name":"Kantine","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Ochsen":{"tags":{"name":"Ochsen","amenity":"restaurant"},"name":"Ochsen","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Spur":{"tags":{"name":"Spur","amenity":"restaurant"},"name":"Spur","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Mykonos":{"tags":{"name":"Mykonos","amenity":"restaurant"},"name":"Mykonos","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Lotus":{"tags":{"name":"Lotus","amenity":"restaurant"},"name":"Lotus","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Applebee's":{"tags":{"name":"Applebee's","amenity":"restaurant"},"name":"Applebee's","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Flunch":{"tags":{"name":"Flunch","amenity":"restaurant"},"name":"Flunch","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Zur Post":{"tags":{"name":"Zur Post","amenity":"restaurant"},"name":"Zur Post","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/China Town":{"tags":{"name":"China Town","amenity":"restaurant"},"name":"China Town","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/La Dolce Vita":{"tags":{"name":"La Dolce Vita","amenity":"restaurant"},"name":"La Dolce Vita","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Waffle House":{"tags":{"name":"Waffle House","amenity":"restaurant"},"name":"Waffle House","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Delphi":{"tags":{"name":"Delphi","amenity":"restaurant"},"name":"Delphi","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Linde":{"tags":{"name":"Linde","amenity":"restaurant"},"name":"Linde","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Outback Steakhouse":{"tags":{"name":"Outback Steakhouse","amenity":"restaurant"},"name":"Outback Steakhouse","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Dionysos":{"tags":{"name":"Dionysos","amenity":"restaurant"},"name":"Dionysos","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Kelsey's":{"tags":{"name":"Kelsey's","amenity":"restaurant"},"name":"Kelsey's","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Boston Pizza":{"tags":{"name":"Boston Pizza","amenity":"restaurant"},"name":"Boston Pizza","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Bella Italia":{"tags":{"name":"Bella Italia","amenity":"restaurant"},"name":"Bella Italia","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Sizzler":{"tags":{"name":"Sizzler","amenity":"restaurant"},"name":"Sizzler","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Grüner Baum":{"tags":{"name":"Grüner Baum","amenity":"restaurant"},"name":"Grüner Baum","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Taj Mahal":{"tags":{"name":"Taj Mahal","amenity":"restaurant"},"name":"Taj Mahal","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Rössli":{"tags":{"name":"Rössli","amenity":"restaurant"},"name":"Rössli","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Traube":{"tags":{"name":"Traube","amenity":"restaurant"},"name":"Traube","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Adria":{"tags":{"name":"Adria","amenity":"restaurant"},"name":"Adria","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Red Robin":{"tags":{"name":"Red Robin","amenity":"restaurant"},"name":"Red Robin","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Roma":{"tags":{"name":"Roma","amenity":"restaurant"},"name":"Roma","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/San Marco":{"tags":{"name":"San Marco","amenity":"restaurant"},"name":"San Marco","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Hellas":{"tags":{"name":"Hellas","amenity":"restaurant"},"name":"Hellas","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/La Perla":{"tags":{"name":"La Perla","amenity":"restaurant"},"name":"La Perla","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Vips":{"tags":{"name":"Vips","amenity":"restaurant"},"name":"Vips","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Panera Bread":{"tags":{"name":"Panera Bread","amenity":"restaurant"},"name":"Panera Bread","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Da Vinci":{"tags":{"name":"Da Vinci","amenity":"restaurant"},"name":"Da Vinci","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Hippopotamus":{"tags":{"name":"Hippopotamus","amenity":"restaurant"},"name":"Hippopotamus","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Prezzo":{"tags":{"name":"Prezzo","amenity":"restaurant"},"name":"Prezzo","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Courtepaille":{"tags":{"name":"Courtepaille","amenity":"restaurant"},"name":"Courtepaille","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Hard Rock Cafe":{"tags":{"name":"Hard Rock Cafe","amenity":"restaurant"},"name":"Hard Rock Cafe","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Panorama":{"tags":{"name":"Panorama","amenity":"restaurant"},"name":"Panorama","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/デニーズ":{"tags":{"name":"デニーズ","amenity":"restaurant"},"name":"デニーズ","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Sportheim":{"tags":{"name":"Sportheim","amenity":"restaurant"},"name":"Sportheim","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/餃子の王将":{"tags":{"name":"餃子の王将","amenity":"restaurant"},"name":"餃子の王将","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Bären":{"tags":{"name":"Bären","amenity":"restaurant"},"name":"Bären","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Alte Post":{"tags":{"name":"Alte Post","amenity":"restaurant"},"name":"Alte Post","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Pizzeria Roma":{"tags":{"name":"Pizzeria Roma","amenity":"restaurant"},"name":"Pizzeria Roma","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/China Garden":{"tags":{"name":"China Garden","amenity":"restaurant"},"name":"China Garden","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Vapiano":{"tags":{"name":"Vapiano","amenity":"restaurant"},"name":"Vapiano","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Mamma Mia":{"tags":{"name":"Mamma Mia","amenity":"restaurant"},"name":"Mamma Mia","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Schwarzer Adler":{"tags":{"name":"Schwarzer Adler","amenity":"restaurant"},"name":"Schwarzer Adler","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/IHOP":{"tags":{"name":"IHOP","amenity":"restaurant"},"name":"IHOP","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Chili's":{"tags":{"name":"Chili's","amenity":"restaurant"},"name":"Chili's","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Asia":{"tags":{"name":"Asia","amenity":"restaurant"},"name":"Asia","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Olive Garden":{"tags":{"name":"Olive Garden","amenity":"restaurant"},"name":"Olive Garden","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/TGI Friday's":{"tags":{"name":"TGI Friday's","amenity":"restaurant"},"name":"TGI Friday's","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Friendly's":{"tags":{"name":"Friendly's","amenity":"restaurant"},"name":"Friendly's","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Buffalo Grill":{"tags":{"name":"Buffalo Grill","amenity":"restaurant"},"name":"Buffalo Grill","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Texas Roadhouse":{"tags":{"name":"Texas Roadhouse","amenity":"restaurant"},"name":"Texas Roadhouse","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/ガスト":{"tags":{"name":"ガスト","name:en":"Gusto","amenity":"restaurant"},"name":"ガスト","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Sakura":{"tags":{"name":"Sakura","amenity":"restaurant"},"name":"Sakura","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Mensa":{"tags":{"name":"Mensa","amenity":"restaurant"},"name":"Mensa","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/The Keg":{"tags":{"name":"The Keg","amenity":"restaurant"},"name":"The Keg","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/サイゼリヤ":{"tags":{"name":"サイゼリヤ","amenity":"restaurant"},"name":"サイゼリヤ","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/La Strada":{"tags":{"name":"La Strada","amenity":"restaurant"},"name":"La Strada","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Village Inn":{"tags":{"name":"Village Inn","amenity":"restaurant"},"name":"Village Inn","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Buffalo Wild Wings":{"tags":{"name":"Buffalo Wild Wings","amenity":"restaurant"},"name":"Buffalo Wild Wings","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Peking":{"tags":{"name":"Peking","amenity":"restaurant"},"name":"Peking","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Round Table Pizza":{"tags":{"name":"Round Table Pizza","amenity":"restaurant"},"name":"Round Table Pizza","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/California Pizza Kitchen":{"tags":{"name":"California Pizza Kitchen","amenity":"restaurant"},"name":"California Pizza Kitchen","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Якитория":{"tags":{"name":"Якитория","amenity":"restaurant"},"name":"Якитория","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Golden Corral":{"tags":{"name":"Golden Corral","amenity":"restaurant"},"name":"Golden Corral","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Perkins":{"tags":{"name":"Perkins","amenity":"restaurant"},"name":"Perkins","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Ruby Tuesday":{"tags":{"name":"Ruby Tuesday","amenity":"restaurant"},"name":"Ruby Tuesday","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Shari's":{"tags":{"name":"Shari's","amenity":"restaurant"},"name":"Shari's","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Bob Evans":{"tags":{"name":"Bob Evans","amenity":"restaurant"},"name":"Bob Evans","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/바다횟집 (Bada Fish Restaurant)":{"tags":{"name":"바다횟집 (Bada Fish Restaurant)","amenity":"restaurant"},"name":"바다횟집 (Bada Fish Restaurant)","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Mang Inasal":{"tags":{"name":"Mang Inasal","amenity":"restaurant"},"name":"Mang Inasal","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Евразия":{"tags":{"name":"Евразия","amenity":"restaurant"},"name":"Евразия","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/ジョナサン":{"tags":{"name":"ジョナサン","amenity":"restaurant"},"name":"ジョナサン","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/restaurant/Longhorn Steakhouse":{"tags":{"name":"Longhorn Steakhouse","amenity":"restaurant"},"name":"Longhorn Steakhouse","icon":"restaurant","geometry":["point","area"],"fields":["cuisine","address","building_area","opening_hours","capacity","takeaway","delivery","smoking"],"suggestion":true},"amenity/bank/Chase":{"tags":{"name":"Chase","amenity":"bank"},"name":"Chase","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Commonwealth Bank":{"tags":{"name":"Commonwealth Bank","amenity":"bank"},"name":"Commonwealth Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Citibank":{"tags":{"name":"Citibank","amenity":"bank"},"name":"Citibank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/HSBC":{"tags":{"name":"HSBC","amenity":"bank"},"name":"HSBC","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Barclays":{"tags":{"name":"Barclays","amenity":"bank"},"name":"Barclays","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Westpac":{"tags":{"name":"Westpac","amenity":"bank"},"name":"Westpac","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/NAB":{"tags":{"name":"NAB","amenity":"bank"},"name":"NAB","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/ANZ":{"tags":{"name":"ANZ","amenity":"bank"},"name":"ANZ","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Lloyds Bank":{"tags":{"name":"Lloyds Bank","amenity":"bank"},"name":"Lloyds Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Landbank":{"tags":{"name":"Landbank","amenity":"bank"},"name":"Landbank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Sparkasse":{"tags":{"name":"Sparkasse","amenity":"bank"},"name":"Sparkasse","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/UCPB":{"tags":{"name":"UCPB","amenity":"bank"},"name":"UCPB","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/PNB":{"tags":{"name":"PNB","amenity":"bank"},"name":"PNB","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Metrobank":{"tags":{"name":"Metrobank","amenity":"bank"},"name":"Metrobank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/BDO":{"tags":{"name":"BDO","amenity":"bank"},"name":"BDO","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Volksbank":{"tags":{"name":"Volksbank","amenity":"bank"},"name":"Volksbank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/BPI":{"tags":{"name":"BPI","amenity":"bank"},"name":"BPI","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Postbank":{"tags":{"name":"Postbank","amenity":"bank"},"name":"Postbank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/NatWest":{"tags":{"name":"NatWest","amenity":"bank"},"name":"NatWest","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Raiffeisenbank":{"tags":{"name":"Raiffeisenbank","amenity":"bank"},"name":"Raiffeisenbank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Yorkshire Bank":{"tags":{"name":"Yorkshire Bank","amenity":"bank"},"name":"Yorkshire Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/ABSA":{"tags":{"name":"ABSA","amenity":"bank"},"name":"ABSA","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Standard Bank":{"tags":{"name":"Standard Bank","amenity":"bank"},"name":"Standard Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/FNB":{"tags":{"name":"FNB","amenity":"bank"},"name":"FNB","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Deutsche Bank":{"tags":{"name":"Deutsche Bank","amenity":"bank"},"name":"Deutsche Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/SEB":{"tags":{"name":"SEB","amenity":"bank"},"name":"SEB","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Commerzbank":{"tags":{"name":"Commerzbank","amenity":"bank"},"name":"Commerzbank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Targobank":{"tags":{"name":"Targobank","amenity":"bank"},"name":"Targobank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/ABN AMRO":{"tags":{"name":"ABN AMRO","amenity":"bank"},"name":"ABN AMRO","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Handelsbanken":{"tags":{"name":"Handelsbanken","amenity":"bank"},"name":"Handelsbanken","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Swedbank":{"tags":{"name":"Swedbank","amenity":"bank"},"name":"Swedbank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Kreissparkasse":{"tags":{"name":"Kreissparkasse","amenity":"bank"},"name":"Kreissparkasse","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/UniCredit Bank":{"tags":{"name":"UniCredit Bank","amenity":"bank"},"name":"UniCredit Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Monte dei Paschi di Siena":{"tags":{"name":"Monte dei Paschi di Siena","amenity":"bank"},"name":"Monte dei Paschi di Siena","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Caja Rural":{"tags":{"name":"Caja Rural","amenity":"bank"},"name":"Caja Rural","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Dresdner Bank":{"tags":{"name":"Dresdner Bank","amenity":"bank"},"name":"Dresdner Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Sparda-Bank":{"tags":{"name":"Sparda-Bank","amenity":"bank"},"name":"Sparda-Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/VÚB":{"tags":{"name":"VÚB","amenity":"bank"},"name":"VÚB","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Slovenská sporiteľňa":{"tags":{"name":"Slovenská sporiteľňa","amenity":"bank"},"name":"Slovenská sporiteľňa","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Bank of Montreal":{"tags":{"name":"Bank of Montreal","amenity":"bank"},"name":"Bank of Montreal","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/KBC":{"tags":{"name":"KBC","amenity":"bank"},"name":"KBC","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Royal Bank of Scotland":{"tags":{"name":"Royal Bank of Scotland","amenity":"bank"},"name":"Royal Bank of Scotland","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/TSB":{"tags":{"name":"TSB","amenity":"bank"},"name":"TSB","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/US Bank":{"tags":{"name":"US Bank","amenity":"bank"},"name":"US Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/HypoVereinsbank":{"tags":{"name":"HypoVereinsbank","amenity":"bank"},"name":"HypoVereinsbank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Bank Austria":{"tags":{"name":"Bank Austria","amenity":"bank"},"name":"Bank Austria","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/ING":{"tags":{"name":"ING","amenity":"bank"},"name":"ING","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Erste Bank":{"tags":{"name":"Erste Bank","amenity":"bank"},"name":"Erste Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/CIBC":{"tags":{"name":"CIBC","amenity":"bank"},"name":"CIBC","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Scotiabank":{"tags":{"name":"Scotiabank","amenity":"bank"},"name":"Scotiabank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Caisse d'Épargne":{"tags":{"name":"Caisse d'Épargne","amenity":"bank"},"name":"Caisse d'Épargne","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Santander":{"tags":{"name":"Santander","amenity":"bank"},"name":"Santander","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Bank of Scotland":{"tags":{"name":"Bank of Scotland","amenity":"bank"},"name":"Bank of Scotland","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/TD Canada Trust":{"tags":{"name":"TD Canada Trust","amenity":"bank"},"name":"TD Canada Trust","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/BMO":{"tags":{"name":"BMO","amenity":"bank"},"name":"BMO","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Danske Bank":{"tags":{"name":"Danske Bank","amenity":"bank"},"name":"Danske Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/OTP":{"tags":{"name":"OTP","amenity":"bank"},"name":"OTP","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Crédit Agricole":{"tags":{"name":"Crédit Agricole","amenity":"bank"},"name":"Crédit Agricole","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/LCL":{"tags":{"name":"LCL","amenity":"bank"},"name":"LCL","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/VR-Bank":{"tags":{"name":"VR-Bank","amenity":"bank"},"name":"VR-Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/ČSOB":{"tags":{"name":"ČSOB","amenity":"bank"},"name":"ČSOB","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Česká spořitelna":{"tags":{"name":"Česká spořitelna","amenity":"bank"},"name":"Česká spořitelna","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/BNP":{"tags":{"name":"BNP","amenity":"bank"},"name":"BNP","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Royal Bank":{"tags":{"name":"Royal Bank","amenity":"bank"},"name":"Royal Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Nationwide":{"tags":{"name":"Nationwide","amenity":"bank"},"name":"Nationwide","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Halifax":{"tags":{"name":"Halifax","amenity":"bank"},"name":"Halifax","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/BAWAG PSK":{"tags":{"name":"BAWAG PSK","amenity":"bank"},"name":"BAWAG PSK","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/National Bank":{"tags":{"name":"National Bank","amenity":"bank"},"name":"National Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Nedbank":{"tags":{"name":"Nedbank","amenity":"bank"},"name":"Nedbank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/First National Bank":{"tags":{"name":"First National Bank","amenity":"bank"},"name":"First National Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Nordea":{"tags":{"name":"Nordea","amenity":"bank"},"name":"Nordea","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Rabobank":{"tags":{"name":"Rabobank","amenity":"bank"},"name":"Rabobank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Sparkasse KölnBonn":{"tags":{"name":"Sparkasse KölnBonn","amenity":"bank"},"name":"Sparkasse KölnBonn","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Tatra banka":{"tags":{"name":"Tatra banka","amenity":"bank"},"name":"Tatra banka","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Berliner Sparkasse":{"tags":{"name":"Berliner Sparkasse","amenity":"bank"},"name":"Berliner Sparkasse","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Berliner Volksbank":{"tags":{"name":"Berliner Volksbank","amenity":"bank"},"name":"Berliner Volksbank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Wells Fargo":{"tags":{"name":"Wells Fargo","amenity":"bank"},"name":"Wells Fargo","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Credit Suisse":{"tags":{"name":"Credit Suisse","amenity":"bank"},"name":"Credit Suisse","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Société Générale":{"tags":{"name":"Société Générale","amenity":"bank"},"name":"Société Générale","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Osuuspankki":{"tags":{"name":"Osuuspankki","amenity":"bank"},"name":"Osuuspankki","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Sparkasse Aachen":{"tags":{"name":"Sparkasse Aachen","amenity":"bank"},"name":"Sparkasse Aachen","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Hamburger Sparkasse":{"tags":{"name":"Hamburger Sparkasse","amenity":"bank"},"name":"Hamburger Sparkasse","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Cassa di Risparmio del Veneto":{"tags":{"name":"Cassa di Risparmio del Veneto","amenity":"bank"},"name":"Cassa di Risparmio del Veneto","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/BNP Paribas":{"tags":{"name":"BNP Paribas","amenity":"bank"},"name":"BNP Paribas","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banque Populaire":{"tags":{"name":"Banque Populaire","amenity":"bank"},"name":"Banque Populaire","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/BNP Paribas Fortis":{"tags":{"name":"BNP Paribas Fortis","amenity":"bank"},"name":"BNP Paribas Fortis","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banco Popular":{"tags":{"name":"Banco Popular","amenity":"bank"},"name":"Banco Popular","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Bancaja":{"tags":{"name":"Bancaja","amenity":"bank"},"name":"Bancaja","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banesto":{"tags":{"name":"Banesto","amenity":"bank"},"name":"Banesto","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/La Caixa":{"tags":{"name":"La Caixa","amenity":"bank"},"name":"La Caixa","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Santander Consumer Bank":{"tags":{"name":"Santander Consumer Bank","amenity":"bank"},"name":"Santander Consumer Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/BRD":{"tags":{"name":"BRD","amenity":"bank"},"name":"BRD","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/BCR":{"tags":{"name":"BCR","amenity":"bank"},"name":"BCR","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banca Transilvania":{"tags":{"name":"Banca Transilvania","amenity":"bank"},"name":"Banca Transilvania","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/BW-Bank":{"tags":{"name":"BW-Bank","amenity":"bank"},"name":"BW-Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Komerční banka":{"tags":{"name":"Komerční banka","amenity":"bank"},"name":"Komerční banka","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banco Pastor":{"tags":{"name":"Banco Pastor","amenity":"bank"},"name":"Banco Pastor","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Stadtsparkasse":{"tags":{"name":"Stadtsparkasse","amenity":"bank"},"name":"Stadtsparkasse","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Ulster Bank":{"tags":{"name":"Ulster Bank","amenity":"bank"},"name":"Ulster Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Sberbank":{"tags":{"name":"Sberbank","amenity":"bank"},"name":"Sberbank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/CIC":{"tags":{"name":"CIC","amenity":"bank"},"name":"CIC","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Bancpost":{"tags":{"name":"Bancpost","amenity":"bank"},"name":"Bancpost","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Caja Madrid":{"tags":{"name":"Caja Madrid","amenity":"bank"},"name":"Caja Madrid","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Maybank":{"tags":{"name":"Maybank","amenity":"bank"},"name":"Maybank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/中国银行":{"tags":{"name":"中国银行","amenity":"bank"},"name":"中国银行","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Unicredit Banca":{"tags":{"name":"Unicredit Banca","amenity":"bank"},"name":"Unicredit Banca","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Crédit Mutuel":{"tags":{"name":"Crédit Mutuel","amenity":"bank"},"name":"Crédit Mutuel","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/BBVA":{"tags":{"name":"BBVA","amenity":"bank"},"name":"BBVA","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Intesa San Paolo":{"tags":{"name":"Intesa San Paolo","amenity":"bank"},"name":"Intesa San Paolo","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/TD Bank":{"tags":{"name":"TD Bank","amenity":"bank"},"name":"TD Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Belfius":{"tags":{"name":"Belfius","amenity":"bank"},"name":"Belfius","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Bank of America":{"tags":{"name":"Bank of America","amenity":"bank"},"name":"Bank of America","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/RBC":{"tags":{"name":"RBC","amenity":"bank"},"name":"RBC","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Alpha Bank":{"tags":{"name":"Alpha Bank","amenity":"bank"},"name":"Alpha Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Сбербанк":{"tags":{"name":"Сбербанк","amenity":"bank"},"name":"Сбербанк","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Россельхозбанк":{"tags":{"name":"Россельхозбанк","amenity":"bank"},"name":"Россельхозбанк","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Crédit du Nord":{"tags":{"name":"Crédit du Nord","amenity":"bank"},"name":"Crédit du Nord","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/BancoEstado":{"tags":{"name":"BancoEstado","amenity":"bank"},"name":"BancoEstado","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Millennium Bank":{"tags":{"name":"Millennium Bank","amenity":"bank"},"name":"Millennium Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/State Bank of India":{"tags":{"name":"State Bank of India","amenity":"bank"},"name":"State Bank of India","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Беларусбанк":{"tags":{"name":"Беларусбанк","amenity":"bank"},"name":"Беларусбанк","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/ING Bank Śląski":{"tags":{"name":"ING Bank Śląski","amenity":"bank"},"name":"ING Bank Śląski","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Caixa Geral de Depósitos":{"tags":{"name":"Caixa Geral de Depósitos","amenity":"bank"},"name":"Caixa Geral de Depósitos","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Kreissparkasse Köln":{"tags":{"name":"Kreissparkasse Köln","amenity":"bank"},"name":"Kreissparkasse Köln","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banco BCI":{"tags":{"name":"Banco BCI","amenity":"bank"},"name":"Banco BCI","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banco de Chile":{"tags":{"name":"Banco de Chile","amenity":"bank"},"name":"Banco de Chile","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/ВТБ24":{"tags":{"name":"ВТБ24","amenity":"bank"},"name":"ВТБ24","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/UBS":{"tags":{"name":"UBS","amenity":"bank"},"name":"UBS","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/PKO BP":{"tags":{"name":"PKO BP","amenity":"bank"},"name":"PKO BP","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Chinabank":{"tags":{"name":"Chinabank","amenity":"bank"},"name":"Chinabank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/PSBank":{"tags":{"name":"PSBank","amenity":"bank"},"name":"PSBank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Union Bank":{"tags":{"name":"Union Bank","amenity":"bank"},"name":"Union Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/China Bank":{"tags":{"name":"China Bank","amenity":"bank"},"name":"China Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/RCBC":{"tags":{"name":"RCBC","amenity":"bank"},"name":"RCBC","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Unicaja":{"tags":{"name":"Unicaja","amenity":"bank"},"name":"Unicaja","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/BBK":{"tags":{"name":"BBK","amenity":"bank"},"name":"BBK","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Ibercaja":{"tags":{"name":"Ibercaja","amenity":"bank"},"name":"Ibercaja","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/RBS":{"tags":{"name":"RBS","amenity":"bank"},"name":"RBS","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Commercial Bank of Ceylon PLC":{"tags":{"name":"Commercial Bank of Ceylon PLC","amenity":"bank"},"name":"Commercial Bank of Ceylon PLC","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Bank of Ireland":{"tags":{"name":"Bank of Ireland","amenity":"bank"},"name":"Bank of Ireland","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/BNL":{"tags":{"name":"BNL","amenity":"bank"},"name":"BNL","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banco Santander":{"tags":{"name":"Banco Santander","amenity":"bank"},"name":"Banco Santander","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banco Itaú":{"tags":{"name":"Banco Itaú","amenity":"bank"},"name":"Banco Itaú","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/AIB":{"tags":{"name":"AIB","amenity":"bank"},"name":"AIB","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/BZ WBK":{"tags":{"name":"BZ WBK","amenity":"bank"},"name":"BZ WBK","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banco do Brasil":{"tags":{"name":"Banco do Brasil","amenity":"bank"},"name":"Banco do Brasil","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Caixa Econômica Federal":{"tags":{"name":"Caixa Econômica Federal","amenity":"bank"},"name":"Caixa Econômica Federal","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Fifth Third Bank":{"tags":{"name":"Fifth Third Bank","amenity":"bank"},"name":"Fifth Third Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banca Popolare di Vicenza":{"tags":{"name":"Banca Popolare di Vicenza","amenity":"bank"},"name":"Banca Popolare di Vicenza","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Wachovia":{"tags":{"name":"Wachovia","amenity":"bank"},"name":"Wachovia","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/OLB":{"tags":{"name":"OLB","amenity":"bank"},"name":"OLB","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/みずほ銀行":{"tags":{"name":"みずほ銀行","amenity":"bank"},"name":"みずほ銀行","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/BES":{"tags":{"name":"BES","amenity":"bank"},"name":"BES","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/ICICI Bank":{"tags":{"name":"ICICI Bank","amenity":"bank"},"name":"ICICI Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/HDFC Bank":{"tags":{"name":"HDFC Bank","amenity":"bank"},"name":"HDFC Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/La Banque Postale":{"tags":{"name":"La Banque Postale","amenity":"bank"},"name":"La Banque Postale","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Pekao SA":{"tags":{"name":"Pekao SA","amenity":"bank"},"name":"Pekao SA","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Oberbank":{"tags":{"name":"Oberbank","amenity":"bank"},"name":"Oberbank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Bradesco":{"tags":{"name":"Bradesco","amenity":"bank"},"name":"Bradesco","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Oldenburgische Landesbank":{"tags":{"name":"Oldenburgische Landesbank","amenity":"bank"},"name":"Oldenburgische Landesbank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Bendigo Bank":{"tags":{"name":"Bendigo Bank","amenity":"bank"},"name":"Bendigo Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Argenta":{"tags":{"name":"Argenta","amenity":"bank"},"name":"Argenta","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/AXA":{"tags":{"name":"AXA","amenity":"bank"},"name":"AXA","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Axis Bank":{"tags":{"name":"Axis Bank","amenity":"bank"},"name":"Axis Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banco Nación":{"tags":{"name":"Banco Nación","amenity":"bank"},"name":"Banco Nación","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/GE Money Bank":{"tags":{"name":"GE Money Bank","amenity":"bank"},"name":"GE Money Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Альфа-Банк":{"tags":{"name":"Альфа-Банк","amenity":"bank"},"name":"Альфа-Банк","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Белагропромбанк":{"tags":{"name":"Белагропромбанк","amenity":"bank"},"name":"Белагропромбанк","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Caja Círculo":{"tags":{"name":"Caja Círculo","amenity":"bank"},"name":"Caja Círculo","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banco Galicia":{"tags":{"name":"Banco Galicia","amenity":"bank"},"name":"Banco Galicia","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Eurobank":{"tags":{"name":"Eurobank","amenity":"bank"},"name":"Eurobank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banca Intesa":{"tags":{"name":"Banca Intesa","amenity":"bank"},"name":"Banca Intesa","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Canara Bank":{"tags":{"name":"Canara Bank","amenity":"bank"},"name":"Canara Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Cajamar":{"tags":{"name":"Cajamar","amenity":"bank"},"name":"Cajamar","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banamex":{"tags":{"name":"Banamex","amenity":"bank"},"name":"Banamex","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Crédit Mutuel de Bretagne":{"tags":{"name":"Crédit Mutuel de Bretagne","amenity":"bank"},"name":"Crédit Mutuel de Bretagne","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Davivienda":{"tags":{"name":"Davivienda","amenity":"bank"},"name":"Davivienda","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Bank Spółdzielczy":{"tags":{"name":"Bank Spółdzielczy","amenity":"bank"},"name":"Bank Spółdzielczy","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Credit Agricole":{"tags":{"name":"Credit Agricole","amenity":"bank"},"name":"Credit Agricole","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Bankinter":{"tags":{"name":"Bankinter","amenity":"bank"},"name":"Bankinter","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banque Nationale":{"tags":{"name":"Banque Nationale","amenity":"bank"},"name":"Banque Nationale","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Bank of the West":{"tags":{"name":"Bank of the West","amenity":"bank"},"name":"Bank of the West","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Key Bank":{"tags":{"name":"Key Bank","amenity":"bank"},"name":"Key Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Western Union":{"tags":{"name":"Western Union","amenity":"bank"},"name":"Western Union","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Citizens Bank":{"tags":{"name":"Citizens Bank","amenity":"bank"},"name":"Citizens Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/ПриватБанк":{"tags":{"name":"ПриватБанк","amenity":"bank"},"name":"ПриватБанк","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Security Bank":{"tags":{"name":"Security Bank","amenity":"bank"},"name":"Security Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Millenium":{"tags":{"name":"Millenium","amenity":"bank"},"name":"Millenium","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Bankia":{"tags":{"name":"Bankia","amenity":"bank"},"name":"Bankia","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/三菱東京UFJ銀行":{"tags":{"name":"三菱東京UFJ銀行","amenity":"bank"},"name":"三菱東京UFJ銀行","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Caixa":{"tags":{"name":"Caixa","amenity":"bank"},"name":"Caixa","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banco de Costa Rica":{"tags":{"name":"Banco de Costa Rica","amenity":"bank"},"name":"Banco de Costa Rica","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/SunTrust Bank":{"tags":{"name":"SunTrust Bank","amenity":"bank"},"name":"SunTrust Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Itaú":{"tags":{"name":"Itaú","amenity":"bank"},"name":"Itaú","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/PBZ":{"tags":{"name":"PBZ","amenity":"bank"},"name":"PBZ","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/中国工商银行":{"tags":{"name":"中国工商银行","amenity":"bank"},"name":"中国工商银行","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Bancolombia":{"tags":{"name":"Bancolombia","amenity":"bank"},"name":"Bancolombia","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Райффайзен Банк Аваль":{"tags":{"name":"Райффайзен Банк Аваль","amenity":"bank"},"name":"Райффайзен Банк Аваль","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Bancomer":{"tags":{"name":"Bancomer","amenity":"bank"},"name":"Bancomer","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banorte":{"tags":{"name":"Banorte","amenity":"bank"},"name":"Banorte","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Alior Bank":{"tags":{"name":"Alior Bank","amenity":"bank"},"name":"Alior Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/BOC":{"tags":{"name":"BOC","amenity":"bank"},"name":"BOC","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Банк Москвы":{"tags":{"name":"Банк Москвы","amenity":"bank"},"name":"Банк Москвы","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/ВТБ":{"tags":{"name":"ВТБ","amenity":"bank"},"name":"ВТБ","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Getin Bank":{"tags":{"name":"Getin Bank","amenity":"bank"},"name":"Getin Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Caja Duero":{"tags":{"name":"Caja Duero","amenity":"bank"},"name":"Caja Duero","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Regions Bank":{"tags":{"name":"Regions Bank","amenity":"bank"},"name":"Regions Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Росбанк":{"tags":{"name":"Росбанк","amenity":"bank"},"name":"Росбанк","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banco Estado":{"tags":{"name":"Banco Estado","amenity":"bank"},"name":"Banco Estado","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/BCI":{"tags":{"name":"BCI","amenity":"bank"},"name":"BCI","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/SunTrust":{"tags":{"name":"SunTrust","amenity":"bank"},"name":"SunTrust","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/PNC Bank":{"tags":{"name":"PNC Bank","amenity":"bank"},"name":"PNC Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/신한은행":{"tags":{"name":"신한은행","name:en":"Sinhan Bank","amenity":"bank"},"name":"신한은행","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/우리은행":{"tags":{"name":"우리은행","name:en":"Uri Bank","amenity":"bank"},"name":"우리은행","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/국민은행":{"tags":{"name":"국민은행","name:en":"Gungmin Bank","amenity":"bank"},"name":"국민은행","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/중소기업은행":{"tags":{"name":"중소기업은행","name:en":"Industrial Bank of Korea","amenity":"bank"},"name":"중소기업은행","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/광주은행":{"tags":{"name":"광주은행","name:en":"Gwangju Bank","amenity":"bank"},"name":"광주은행","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Газпромбанк":{"tags":{"name":"Газпромбанк","amenity":"bank"},"name":"Газпромбанк","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/M&T Bank":{"tags":{"name":"M&T Bank","amenity":"bank"},"name":"M&T Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Caja de Burgos":{"tags":{"name":"Caja de Burgos","amenity":"bank"},"name":"Caja de Burgos","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Santander Totta":{"tags":{"name":"Santander Totta","amenity":"bank"},"name":"Santander Totta","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/УкрСиббанк":{"tags":{"name":"УкрСиббанк","amenity":"bank"},"name":"УкрСиббанк","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Ощадбанк":{"tags":{"name":"Ощадбанк","amenity":"bank"},"name":"Ощадбанк","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Уралсиб":{"tags":{"name":"Уралсиб","amenity":"bank"},"name":"Уралсиб","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/りそな銀行":{"tags":{"name":"りそな銀行","name:en":"Mizuho Bank","amenity":"bank"},"name":"りそな銀行","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Ecobank":{"tags":{"name":"Ecobank","amenity":"bank"},"name":"Ecobank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Cajero Automatico Bancared":{"tags":{"name":"Cajero Automatico Bancared","amenity":"bank"},"name":"Cajero Automatico Bancared","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Промсвязьбанк":{"tags":{"name":"Промсвязьбанк","amenity":"bank"},"name":"Промсвязьбанк","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/三井住友銀行":{"tags":{"name":"三井住友銀行","amenity":"bank"},"name":"三井住友銀行","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banco Provincia":{"tags":{"name":"Banco Provincia","amenity":"bank"},"name":"Banco Provincia","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/BB&T":{"tags":{"name":"BB&T","amenity":"bank"},"name":"BB&T","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Возрождение":{"tags":{"name":"Возрождение","amenity":"bank"},"name":"Возрождение","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Capital One":{"tags":{"name":"Capital One","amenity":"bank"},"name":"Capital One","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/横浜銀行":{"tags":{"name":"横浜銀行","amenity":"bank"},"name":"横浜銀行","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Bank Mandiri":{"tags":{"name":"Bank Mandiri","amenity":"bank"},"name":"Bank Mandiri","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banco de la Nación":{"tags":{"name":"Banco de la Nación","amenity":"bank"},"name":"Banco de la Nación","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banco G&T Continental":{"tags":{"name":"Banco G&T Continental","amenity":"bank"},"name":"Banco G&T Continental","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Peoples Bank":{"tags":{"name":"Peoples Bank","amenity":"bank"},"name":"Peoples Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/工商银行":{"tags":{"name":"工商银行","amenity":"bank"},"name":"工商银行","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Совкомбанк":{"tags":{"name":"Совкомбанк","amenity":"bank"},"name":"Совкомбанк","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Provincial":{"tags":{"name":"Provincial","amenity":"bank"},"name":"Provincial","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banco de Desarrollo Banrural":{"tags":{"name":"Banco de Desarrollo Banrural","amenity":"bank"},"name":"Banco de Desarrollo Banrural","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banco Bradesco":{"tags":{"name":"Banco Bradesco","amenity":"bank"},"name":"Banco Bradesco","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Bicentenario":{"tags":{"name":"Bicentenario","amenity":"bank"},"name":"Bicentenario","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/ლიბერთი ბანკი":{"tags":{"name":"ლიბერთი ბანკი","name:en":"Liberty Bank","amenity":"bank"},"name":"ლიბერთი ბანკი","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Banesco":{"tags":{"name":"Banesco","amenity":"bank"},"name":"Banesco","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Mercantil":{"tags":{"name":"Mercantil","amenity":"bank"},"name":"Mercantil","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Bank BRI":{"tags":{"name":"Bank BRI","amenity":"bank"},"name":"Bank BRI","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/Del Tesoro":{"tags":{"name":"Del Tesoro","amenity":"bank"},"name":"Del Tesoro","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/하나은행":{"tags":{"name":"하나은행","amenity":"bank"},"name":"하나은행","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/CityCommerce Bank":{"tags":{"name":"CityCommerce Bank","amenity":"bank"},"name":"CityCommerce Bank","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/bank/De Venezuela":{"tags":{"name":"De Venezuela","amenity":"bank"},"name":"De Venezuela","icon":"bank","geometry":["point","area"],"fields":["atm","operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/car_rental/Europcar":{"tags":{"name":"Europcar","amenity":"car_rental"},"name":"Europcar","icon":"car","geometry":["point","area"],"fields":["operator"],"suggestion":true},"amenity/car_rental/Budget":{"tags":{"name":"Budget","amenity":"car_rental"},"name":"Budget","icon":"car","geometry":["point","area"],"fields":["operator"],"suggestion":true},"amenity/car_rental/Sixt":{"tags":{"name":"Sixt","amenity":"car_rental"},"name":"Sixt","icon":"car","geometry":["point","area"],"fields":["operator"],"suggestion":true},"amenity/car_rental/Avis":{"tags":{"name":"Avis","amenity":"car_rental"},"name":"Avis","icon":"car","geometry":["point","area"],"fields":["operator"],"suggestion":true},"amenity/car_rental/Hertz":{"tags":{"name":"Hertz","amenity":"car_rental"},"name":"Hertz","icon":"car","geometry":["point","area"],"fields":["operator"],"suggestion":true},"amenity/car_rental/Enterprise":{"tags":{"name":"Enterprise","amenity":"car_rental"},"name":"Enterprise","icon":"car","geometry":["point","area"],"fields":["operator"],"suggestion":true},"amenity/car_rental/stadtmobil CarSharing-Station":{"tags":{"name":"stadtmobil CarSharing-Station","amenity":"car_rental"},"name":"stadtmobil CarSharing-Station","icon":"car","geometry":["point","area"],"fields":["operator"],"suggestion":true},"amenity/pharmacy/Rowlands Pharmacy":{"tags":{"name":"Rowlands Pharmacy","amenity":"pharmacy"},"name":"Rowlands Pharmacy","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Boots":{"tags":{"name":"Boots","amenity":"pharmacy"},"name":"Boots","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Marien-Apotheke":{"tags":{"name":"Marien-Apotheke","amenity":"pharmacy"},"name":"Marien-Apotheke","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Mercury Drug":{"tags":{"name":"Mercury Drug","amenity":"pharmacy"},"name":"Mercury Drug","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Löwen-Apotheke":{"tags":{"name":"Löwen-Apotheke","amenity":"pharmacy"},"name":"Löwen-Apotheke","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Superdrug":{"tags":{"name":"Superdrug","amenity":"pharmacy"},"name":"Superdrug","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Sonnen-Apotheke":{"tags":{"name":"Sonnen-Apotheke","amenity":"pharmacy"},"name":"Sonnen-Apotheke","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Rathaus-Apotheke":{"tags":{"name":"Rathaus-Apotheke","amenity":"pharmacy"},"name":"Rathaus-Apotheke","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Engel-Apotheke":{"tags":{"name":"Engel-Apotheke","amenity":"pharmacy"},"name":"Engel-Apotheke","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Hirsch-Apotheke":{"tags":{"name":"Hirsch-Apotheke","amenity":"pharmacy"},"name":"Hirsch-Apotheke","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Stern-Apotheke":{"tags":{"name":"Stern-Apotheke","amenity":"pharmacy"},"name":"Stern-Apotheke","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Lloyds Pharmacy":{"tags":{"name":"Lloyds Pharmacy","amenity":"pharmacy"},"name":"Lloyds Pharmacy","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Rosen-Apotheke":{"tags":{"name":"Rosen-Apotheke","amenity":"pharmacy"},"name":"Rosen-Apotheke","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Stadt-Apotheke":{"tags":{"name":"Stadt-Apotheke","amenity":"pharmacy"},"name":"Stadt-Apotheke","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Markt-Apotheke":{"tags":{"name":"Markt-Apotheke","amenity":"pharmacy"},"name":"Markt-Apotheke","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Аптека":{"tags":{"name":"Аптека","amenity":"pharmacy"},"name":"Аптека","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Pharmasave":{"tags":{"name":"Pharmasave","amenity":"pharmacy"},"name":"Pharmasave","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Brunnen-Apotheke":{"tags":{"name":"Brunnen-Apotheke","amenity":"pharmacy"},"name":"Brunnen-Apotheke","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Shoppers Drug Mart":{"tags":{"name":"Shoppers Drug Mart","amenity":"pharmacy"},"name":"Shoppers Drug Mart","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Apotheke am Markt":{"tags":{"name":"Apotheke am Markt","amenity":"pharmacy"},"name":"Apotheke am Markt","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Alte Apotheke":{"tags":{"name":"Alte Apotheke","amenity":"pharmacy"},"name":"Alte Apotheke","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Neue Apotheke":{"tags":{"name":"Neue Apotheke","amenity":"pharmacy"},"name":"Neue Apotheke","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Gintarinė vaistinė":{"tags":{"name":"Gintarinė vaistinė","amenity":"pharmacy"},"name":"Gintarinė vaistinė","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Rats-Apotheke":{"tags":{"name":"Rats-Apotheke","amenity":"pharmacy"},"name":"Rats-Apotheke","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Adler Apotheke":{"tags":{"name":"Adler Apotheke","amenity":"pharmacy"},"name":"Adler Apotheke","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Pharmacie Centrale":{"tags":{"name":"Pharmacie Centrale","amenity":"pharmacy"},"name":"Pharmacie Centrale","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Walgreens":{"tags":{"name":"Walgreens","amenity":"pharmacy"},"name":"Walgreens","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Rite Aid":{"tags":{"name":"Rite Aid","amenity":"pharmacy"},"name":"Rite Aid","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Apotheke":{"tags":{"name":"Apotheke","amenity":"pharmacy"},"name":"Apotheke","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Linden-Apotheke":{"tags":{"name":"Linden-Apotheke","amenity":"pharmacy"},"name":"Linden-Apotheke","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Bahnhof-Apotheke":{"tags":{"name":"Bahnhof-Apotheke","amenity":"pharmacy"},"name":"Bahnhof-Apotheke","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Burg-Apotheke":{"tags":{"name":"Burg-Apotheke","amenity":"pharmacy"},"name":"Burg-Apotheke","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Jean Coutu":{"tags":{"name":"Jean Coutu","amenity":"pharmacy"},"name":"Jean Coutu","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Pharmaprix":{"tags":{"name":"Pharmaprix","amenity":"pharmacy"},"name":"Pharmaprix","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Farmacias Ahumada":{"tags":{"name":"Farmacias Ahumada","amenity":"pharmacy"},"name":"Farmacias Ahumada","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Farmacia Comunale":{"tags":{"name":"Farmacia Comunale","amenity":"pharmacy"},"name":"Farmacia Comunale","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Farmacias Cruz Verde":{"tags":{"name":"Farmacias Cruz Verde","amenity":"pharmacy"},"name":"Farmacias Cruz Verde","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Cruz Verde":{"tags":{"name":"Cruz Verde","amenity":"pharmacy"},"name":"Cruz Verde","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Hubertus Apotheke":{"tags":{"name":"Hubertus Apotheke","amenity":"pharmacy"},"name":"Hubertus Apotheke","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/CVS":{"tags":{"name":"CVS","amenity":"pharmacy"},"name":"CVS","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Farmacias SalcoBrand":{"tags":{"name":"Farmacias SalcoBrand","amenity":"pharmacy"},"name":"Farmacias SalcoBrand","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Фармация":{"tags":{"name":"Фармация","amenity":"pharmacy"},"name":"Фармация","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Bären-Apotheke":{"tags":{"name":"Bären-Apotheke","amenity":"pharmacy"},"name":"Bären-Apotheke","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Clicks":{"tags":{"name":"Clicks","amenity":"pharmacy"},"name":"Clicks","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/セイジョー":{"tags":{"name":"セイジョー","amenity":"pharmacy"},"name":"セイジョー","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/マツモトキヨシ":{"tags":{"name":"マツモトキヨシ","amenity":"pharmacy"},"name":"マツモトキヨシ","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Dr. Max":{"tags":{"name":"Dr. Max","amenity":"pharmacy"},"name":"Dr. Max","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Вита":{"tags":{"name":"Вита","amenity":"pharmacy"},"name":"Вита","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/サンドラッグ":{"tags":{"name":"サンドラッグ","amenity":"pharmacy"},"name":"サンドラッグ","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Apteka":{"tags":{"name":"Apteka","amenity":"pharmacy"},"name":"Apteka","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Первая помощь":{"tags":{"name":"Первая помощь","amenity":"pharmacy"},"name":"Первая помощь","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Ригла":{"tags":{"name":"Ригла","amenity":"pharmacy"},"name":"Ригла","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Имплозия":{"tags":{"name":"Имплозия","amenity":"pharmacy"},"name":"Имплозия","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Kinney Drugs":{"tags":{"name":"Kinney Drugs","amenity":"pharmacy"},"name":"Kinney Drugs","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Классика":{"tags":{"name":"Классика","amenity":"pharmacy"},"name":"Классика","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Ljekarna":{"tags":{"name":"Ljekarna","amenity":"pharmacy"},"name":"Ljekarna","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/SalcoBrand":{"tags":{"name":"SalcoBrand","amenity":"pharmacy"},"name":"SalcoBrand","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Аптека 36,6":{"tags":{"name":"Аптека 36,6","amenity":"pharmacy"},"name":"Аптека 36,6","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Фармакор":{"tags":{"name":"Фармакор","amenity":"pharmacy"},"name":"Фармакор","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/スギ薬局":{"tags":{"name":"スギ薬局","amenity":"pharmacy"},"name":"スギ薬局","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Аптечный пункт":{"tags":{"name":"Аптечный пункт","amenity":"pharmacy"},"name":"Аптечный пункт","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Невис":{"tags":{"name":"Невис","amenity":"pharmacy"},"name":"Невис","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/トモズ (Tomod's)":{"tags":{"name":"トモズ (Tomod's)","amenity":"pharmacy"},"name":"トモズ (Tomod's)","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Eurovaistinė":{"tags":{"name":"Eurovaistinė","amenity":"pharmacy"},"name":"Eurovaistinė","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Farmacity":{"tags":{"name":"Farmacity","amenity":"pharmacy"},"name":"Farmacity","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/аптека":{"tags":{"name":"аптека","amenity":"pharmacy"},"name":"аптека","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/The Generics Pharmacy":{"tags":{"name":"The Generics Pharmacy","amenity":"pharmacy"},"name":"The Generics Pharmacy","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Farmatodo":{"tags":{"name":"Farmatodo","amenity":"pharmacy"},"name":"Farmatodo","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Duane Reade":{"tags":{"name":"Duane Reade","amenity":"pharmacy"},"name":"Duane Reade","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Фармленд":{"tags":{"name":"Фармленд","amenity":"pharmacy"},"name":"Фармленд","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/ドラッグてらしま (Drug Terashima)":{"tags":{"name":"ドラッグてらしま (Drug Terashima)","amenity":"pharmacy"},"name":"ドラッグてらしま (Drug Terashima)","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Арніка":{"tags":{"name":"Арніка","amenity":"pharmacy"},"name":"Арніка","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/ავერსი (Aversi)":{"tags":{"name":"ავერსი (Aversi)","amenity":"pharmacy"},"name":"ავერსი (Aversi)","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/pharmacy/Farmahorro":{"tags":{"name":"Farmahorro","amenity":"pharmacy"},"name":"Farmahorro","icon":"pharmacy","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"amenity/cafe/Starbucks":{"tags":{"name":"Starbucks","cuisine":"coffee_shop","amenity":"cafe"},"name":"Starbucks","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/Cafeteria":{"tags":{"name":"Cafeteria","amenity":"cafe"},"name":"Cafeteria","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/Costa":{"tags":{"name":"Costa","amenity":"cafe"},"name":"Costa","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/Caffè Nero":{"tags":{"name":"Caffè Nero","amenity":"cafe"},"name":"Caffè Nero","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/Кафе":{"tags":{"name":"Кафе","amenity":"cafe"},"name":"Кафе","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/Café Central":{"tags":{"name":"Café Central","amenity":"cafe"},"name":"Café Central","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/Second Cup":{"tags":{"name":"Second Cup","amenity":"cafe"},"name":"Second Cup","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/Dunkin Donuts":{"tags":{"name":"Dunkin Donuts","cuisine":"donut","amenity":"cafe"},"name":"Dunkin Donuts","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/Espresso House":{"tags":{"name":"Espresso House","amenity":"cafe"},"name":"Espresso House","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/Segafredo":{"tags":{"name":"Segafredo","amenity":"cafe"},"name":"Segafredo","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/Coffee Time":{"tags":{"name":"Coffee Time","amenity":"cafe"},"name":"Coffee Time","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/Cafe Coffee Day":{"tags":{"name":"Cafe Coffee Day","amenity":"cafe"},"name":"Cafe Coffee Day","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/Eiscafe Venezia":{"tags":{"name":"Eiscafe Venezia","amenity":"cafe"},"name":"Eiscafe Venezia","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/スターバックス":{"tags":{"name":"スターバックス","name:en":"Starbucks","amenity":"cafe"},"name":"スターバックス","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/Шоколадница":{"tags":{"name":"Шоколадница","amenity":"cafe"},"name":"Шоколадница","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/Pret A Manger":{"tags":{"name":"Pret A Manger","amenity":"cafe"},"name":"Pret A Manger","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/Столовая":{"tags":{"name":"Столовая","amenity":"cafe"},"name":"Столовая","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/ドトール":{"tags":{"name":"ドトール","name:en":"DOUTOR","amenity":"cafe"},"name":"ドトール","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/Tchibo":{"tags":{"name":"Tchibo","amenity":"cafe"},"name":"Tchibo","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/Кофе Хауз":{"tags":{"name":"Кофе Хауз","amenity":"cafe"},"name":"Кофе Хауз","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/Caribou Coffee":{"tags":{"name":"Caribou Coffee","amenity":"cafe"},"name":"Caribou Coffee","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/Уют":{"tags":{"name":"Уют","amenity":"cafe"},"name":"Уют","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/Шашлычная":{"tags":{"name":"Шашлычная","amenity":"cafe"},"name":"Шашлычная","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/คาเฟ่ อเมซอน":{"tags":{"name":"คาเฟ่ อเมซอน","amenity":"cafe"},"name":"คาเฟ่ อเมซอน","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/Traveler's Coffee":{"tags":{"name":"Traveler's Coffee","amenity":"cafe"},"name":"Traveler's Coffee","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/カフェ・ド・クリエ":{"tags":{"name":"カフェ・ド・クリエ","name:en":"Cafe de CRIE","amenity":"cafe"},"name":"カフェ・ド・クリエ","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"amenity/cafe/Cafe Amazon":{"tags":{"name":"Cafe Amazon","amenity":"cafe"},"name":"Cafe Amazon","icon":"cafe","geometry":["point","area"],"fields":["cuisine","internet_access","address","building_area","opening_hours","smoking"],"suggestion":true},"shop/supermarket/Budgens":{"tags":{"name":"Budgens","shop":"supermarket"},"name":"Budgens","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Morrisons":{"tags":{"name":"Morrisons","shop":"supermarket"},"name":"Morrisons","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Interspar":{"tags":{"name":"Interspar","shop":"supermarket"},"name":"Interspar","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Merkur":{"tags":{"name":"Merkur","shop":"supermarket"},"name":"Merkur","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Sainsbury's":{"tags":{"name":"Sainsbury's","shop":"supermarket"},"name":"Sainsbury's","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Lidl":{"tags":{"name":"Lidl","shop":"supermarket"},"name":"Lidl","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Edeka":{"tags":{"name":"Edeka","shop":"supermarket"},"name":"Edeka","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Coles":{"tags":{"name":"Coles","shop":"supermarket"},"name":"Coles","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Iceland":{"tags":{"name":"Iceland","shop":"supermarket"},"name":"Iceland","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Coop":{"tags":{"name":"Coop","shop":"supermarket"},"name":"Coop","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Tesco":{"tags":{"name":"Tesco","shop":"supermarket"},"name":"Tesco","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Woolworths":{"tags":{"name":"Woolworths","shop":"supermarket"},"name":"Woolworths","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Zielpunkt":{"tags":{"name":"Zielpunkt","shop":"supermarket"},"name":"Zielpunkt","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Nahkauf":{"tags":{"name":"Nahkauf","shop":"supermarket"},"name":"Nahkauf","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Billa":{"tags":{"name":"Billa","shop":"supermarket"},"name":"Billa","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Kaufland":{"tags":{"name":"Kaufland","shop":"supermarket"},"name":"Kaufland","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Plus":{"tags":{"name":"Plus","shop":"supermarket"},"name":"Plus","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/ALDI":{"tags":{"name":"ALDI","shop":"supermarket"},"name":"ALDI","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Checkers":{"tags":{"name":"Checkers","shop":"supermarket"},"name":"Checkers","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Tesco Metro":{"tags":{"name":"Tesco Metro","shop":"supermarket"},"name":"Tesco Metro","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/NP":{"tags":{"name":"NP","shop":"supermarket"},"name":"NP","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Penny":{"tags":{"name":"Penny","shop":"supermarket"},"name":"Penny","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Norma":{"tags":{"name":"Norma","shop":"supermarket"},"name":"Norma","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Asda":{"tags":{"name":"Asda","shop":"supermarket"},"name":"Asda","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Netto":{"tags":{"name":"Netto","shop":"supermarket"},"name":"Netto","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Rewe":{"tags":{"name":"Rewe","shop":"supermarket"},"name":"Rewe","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Aldi Süd":{"tags":{"name":"Aldi Süd","shop":"supermarket"},"name":"Aldi Süd","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Real":{"tags":{"name":"Real","shop":"supermarket"},"name":"Real","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/King Soopers":{"tags":{"name":"King Soopers","shop":"supermarket"},"name":"King Soopers","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Kiwi":{"tags":{"name":"Kiwi","shop":"supermarket"},"name":"Kiwi","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Pick n Pay":{"tags":{"name":"Pick n Pay","shop":"supermarket"},"name":"Pick n Pay","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/ICA":{"tags":{"name":"ICA","shop":"supermarket"},"name":"ICA","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Tengelmann":{"tags":{"name":"Tengelmann","shop":"supermarket"},"name":"Tengelmann","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Carrefour":{"tags":{"name":"Carrefour","shop":"supermarket"},"name":"Carrefour","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Waitrose":{"tags":{"name":"Waitrose","shop":"supermarket"},"name":"Waitrose","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Spar":{"tags":{"name":"Spar","shop":"supermarket"},"name":"Spar","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Hofer":{"tags":{"name":"Hofer","shop":"supermarket"},"name":"Hofer","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/M-Preis":{"tags":{"name":"M-Preis","shop":"supermarket"},"name":"M-Preis","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/tegut":{"tags":{"name":"tegut","shop":"supermarket"},"name":"tegut","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Sainsbury's Local":{"tags":{"name":"Sainsbury's Local","shop":"supermarket"},"name":"Sainsbury's Local","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/E-Center":{"tags":{"name":"E-Center","shop":"supermarket"},"name":"E-Center","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Aldi Nord":{"tags":{"name":"Aldi Nord","shop":"supermarket"},"name":"Aldi Nord","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/nahkauf":{"tags":{"name":"nahkauf","shop":"supermarket"},"name":"nahkauf","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Meijer":{"tags":{"name":"Meijer","shop":"supermarket"},"name":"Meijer","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Safeway":{"tags":{"name":"Safeway","shop":"supermarket"},"name":"Safeway","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Costco":{"tags":{"name":"Costco","shop":"supermarket"},"name":"Costco","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Albert":{"tags":{"name":"Albert","shop":"supermarket"},"name":"Albert","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Jumbo":{"tags":{"name":"Jumbo","shop":"supermarket"},"name":"Jumbo","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Shoprite":{"tags":{"name":"Shoprite","shop":"supermarket"},"name":"Shoprite","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/MPreis":{"tags":{"name":"MPreis","shop":"supermarket"},"name":"MPreis","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Penny Market":{"tags":{"name":"Penny Market","shop":"supermarket"},"name":"Penny Market","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Tesco Extra":{"tags":{"name":"Tesco Extra","shop":"supermarket"},"name":"Tesco Extra","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Albert Heijn":{"tags":{"name":"Albert Heijn","shop":"supermarket"},"name":"Albert Heijn","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/IGA":{"tags":{"name":"IGA","shop":"supermarket"},"name":"IGA","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Super U":{"tags":{"name":"Super U","shop":"supermarket"},"name":"Super U","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Metro":{"tags":{"name":"Metro","shop":"supermarket"},"name":"Metro","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Neukauf":{"tags":{"name":"Neukauf","shop":"supermarket"},"name":"Neukauf","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Migros":{"tags":{"name":"Migros","shop":"supermarket"},"name":"Migros","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Marktkauf":{"tags":{"name":"Marktkauf","shop":"supermarket"},"name":"Marktkauf","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Delikatesy Centrum":{"tags":{"name":"Delikatesy Centrum","shop":"supermarket"},"name":"Delikatesy Centrum","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/C1000":{"tags":{"name":"C1000","shop":"supermarket"},"name":"C1000","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Hoogvliet":{"tags":{"name":"Hoogvliet","shop":"supermarket"},"name":"Hoogvliet","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Food Basics":{"tags":{"name":"Food Basics","shop":"supermarket"},"name":"Food Basics","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Casino":{"tags":{"name":"Casino","shop":"supermarket"},"name":"Casino","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Penny Markt":{"tags":{"name":"Penny Markt","shop":"supermarket"},"name":"Penny Markt","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Giant":{"tags":{"name":"Giant","shop":"supermarket"},"name":"Giant","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Rema 1000":{"tags":{"name":"Rema 1000","shop":"supermarket"},"name":"Rema 1000","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Kaufpark":{"tags":{"name":"Kaufpark","shop":"supermarket"},"name":"Kaufpark","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/ALDI SÜD":{"tags":{"name":"ALDI SÜD","shop":"supermarket"},"name":"ALDI SÜD","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Simply Market":{"tags":{"name":"Simply Market","shop":"supermarket"},"name":"Simply Market","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Konzum":{"tags":{"name":"Konzum","shop":"supermarket"},"name":"Konzum","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Carrefour Express":{"tags":{"name":"Carrefour Express","shop":"supermarket"},"name":"Carrefour Express","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Eurospar":{"tags":{"name":"Eurospar","shop":"supermarket"},"name":"Eurospar","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Mercator":{"tags":{"name":"Mercator","shop":"supermarket"},"name":"Mercator","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Famila":{"tags":{"name":"Famila","shop":"supermarket"},"name":"Famila","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Hemköp":{"tags":{"name":"Hemköp","shop":"supermarket"},"name":"Hemköp","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/real,-":{"tags":{"name":"real,-","shop":"supermarket"},"name":"real,-","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Markant":{"tags":{"name":"Markant","shop":"supermarket"},"name":"Markant","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Volg":{"tags":{"name":"Volg","shop":"supermarket"},"name":"Volg","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Leader Price":{"tags":{"name":"Leader Price","shop":"supermarket"},"name":"Leader Price","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Treff 3000":{"tags":{"name":"Treff 3000","shop":"supermarket"},"name":"Treff 3000","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/SuperBrugsen":{"tags":{"name":"SuperBrugsen","shop":"supermarket"},"name":"SuperBrugsen","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Kaiser's":{"tags":{"name":"Kaiser's","shop":"supermarket"},"name":"Kaiser's","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/K+K":{"tags":{"name":"K+K","shop":"supermarket"},"name":"K+K","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Unimarkt":{"tags":{"name":"Unimarkt","shop":"supermarket"},"name":"Unimarkt","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Carrefour City":{"tags":{"name":"Carrefour City","shop":"supermarket"},"name":"Carrefour City","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Sobeys":{"tags":{"name":"Sobeys","shop":"supermarket"},"name":"Sobeys","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/S-Market":{"tags":{"name":"S-Market","shop":"supermarket"},"name":"S-Market","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Combi":{"tags":{"name":"Combi","shop":"supermarket"},"name":"Combi","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Denner":{"tags":{"name":"Denner","shop":"supermarket"},"name":"Denner","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Konsum":{"tags":{"name":"Konsum","shop":"supermarket"},"name":"Konsum","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Franprix":{"tags":{"name":"Franprix","shop":"supermarket"},"name":"Franprix","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Monoprix":{"tags":{"name":"Monoprix","shop":"supermarket"},"name":"Monoprix","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Diska":{"tags":{"name":"Diska","shop":"supermarket"},"name":"Diska","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/PENNY":{"tags":{"name":"PENNY","shop":"supermarket"},"name":"PENNY","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Dia":{"tags":{"name":"Dia","shop":"supermarket"},"name":"Dia","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Giant Eagle":{"tags":{"name":"Giant Eagle","shop":"supermarket"},"name":"Giant Eagle","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/NORMA":{"tags":{"name":"NORMA","shop":"supermarket"},"name":"NORMA","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/AD Delhaize":{"tags":{"name":"AD Delhaize","shop":"supermarket"},"name":"AD Delhaize","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Auchan":{"tags":{"name":"Auchan","shop":"supermarket"},"name":"Auchan","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Mercadona":{"tags":{"name":"Mercadona","shop":"supermarket"},"name":"Mercadona","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Consum":{"tags":{"name":"Consum","shop":"supermarket"},"name":"Consum","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Carrefour Market":{"tags":{"name":"Carrefour Market","shop":"supermarket"},"name":"Carrefour Market","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Whole Foods":{"tags":{"name":"Whole Foods","shop":"supermarket"},"name":"Whole Foods","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Pam":{"tags":{"name":"Pam","shop":"supermarket"},"name":"Pam","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/sky":{"tags":{"name":"sky","shop":"supermarket"},"name":"sky","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Despar":{"tags":{"name":"Despar","shop":"supermarket"},"name":"Despar","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Eroski":{"tags":{"name":"Eroski","shop":"supermarket"},"name":"Eroski","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Maxi":{"tags":{"name":"Maxi","shop":"supermarket"},"name":"Maxi","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Colruyt":{"tags":{"name":"Colruyt","shop":"supermarket"},"name":"Colruyt","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/The Co-operative":{"tags":{"name":"The Co-operative","shop":"supermarket"},"name":"The Co-operative","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Intermarché":{"tags":{"name":"Intermarché","shop":"supermarket"},"name":"Intermarché","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Delhaize":{"tags":{"name":"Delhaize","shop":"supermarket"},"name":"Delhaize","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/CBA":{"tags":{"name":"CBA","shop":"supermarket"},"name":"CBA","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Shopi":{"tags":{"name":"Shopi","shop":"supermarket"},"name":"Shopi","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Walmart":{"tags":{"name":"Walmart","shop":"supermarket"},"name":"Walmart","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Kroger":{"tags":{"name":"Kroger","shop":"supermarket"},"name":"Kroger","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Albertsons":{"tags":{"name":"Albertsons","shop":"supermarket"},"name":"Albertsons","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Trader Joe's":{"tags":{"name":"Trader Joe's","shop":"supermarket"},"name":"Trader Joe's","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Feneberg":{"tags":{"name":"Feneberg","shop":"supermarket"},"name":"Feneberg","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/denn's Biomarkt":{"tags":{"name":"denn's Biomarkt","shop":"supermarket"},"name":"denn's Biomarkt","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Kvickly":{"tags":{"name":"Kvickly","shop":"supermarket"},"name":"Kvickly","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Makro":{"tags":{"name":"Makro","shop":"supermarket"},"name":"Makro","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Dico":{"tags":{"name":"Dico","shop":"supermarket"},"name":"Dico","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Nah & Frisch":{"tags":{"name":"Nah & Frisch","shop":"supermarket"},"name":"Nah & Frisch","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Champion":{"tags":{"name":"Champion","shop":"supermarket"},"name":"Champion","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/ICA Supermarket":{"tags":{"name":"ICA Supermarket","shop":"supermarket"},"name":"ICA Supermarket","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Fakta":{"tags":{"name":"Fakta","shop":"supermarket"},"name":"Fakta","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Магнит":{"tags":{"name":"Магнит","shop":"supermarket"},"name":"Магнит","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Caprabo":{"tags":{"name":"Caprabo","shop":"supermarket"},"name":"Caprabo","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Famiglia Cooperativa":{"tags":{"name":"Famiglia Cooperativa","shop":"supermarket"},"name":"Famiglia Cooperativa","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Народная 7Я семьЯ":{"tags":{"name":"Народная 7Я семьЯ","shop":"supermarket"},"name":"Народная 7Я семьЯ","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Esselunga":{"tags":{"name":"Esselunga","shop":"supermarket"},"name":"Esselunga","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Maxima":{"tags":{"name":"Maxima","shop":"supermarket"},"name":"Maxima","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Wasgau":{"tags":{"name":"Wasgau","shop":"supermarket"},"name":"Wasgau","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Pingo Doce":{"tags":{"name":"Pingo Doce","shop":"supermarket"},"name":"Pingo Doce","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Match":{"tags":{"name":"Match","shop":"supermarket"},"name":"Match","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Profi":{"tags":{"name":"Profi","shop":"supermarket"},"name":"Profi","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Lider":{"tags":{"name":"Lider","shop":"supermarket"},"name":"Lider","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Unimarc":{"tags":{"name":"Unimarc","shop":"supermarket"},"name":"Unimarc","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/The Co-operative Food":{"tags":{"name":"The Co-operative Food","shop":"supermarket"},"name":"The Co-operative Food","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Santa Isabel":{"tags":{"name":"Santa Isabel","shop":"supermarket"},"name":"Santa Isabel","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Седьмой континент":{"tags":{"name":"Седьмой континент","shop":"supermarket"},"name":"Седьмой континент","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/HIT":{"tags":{"name":"HIT","shop":"supermarket"},"name":"HIT","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Rimi":{"tags":{"name":"Rimi","shop":"supermarket"},"name":"Rimi","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Conad":{"tags":{"name":"Conad","shop":"supermarket"},"name":"Conad","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Фуршет":{"tags":{"name":"Фуршет","shop":"supermarket"},"name":"Фуршет","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Willys":{"tags":{"name":"Willys","shop":"supermarket"},"name":"Willys","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Farmfoods":{"tags":{"name":"Farmfoods","shop":"supermarket"},"name":"Farmfoods","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/U Express":{"tags":{"name":"U Express","shop":"supermarket"},"name":"U Express","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Фора":{"tags":{"name":"Фора","shop":"supermarket"},"name":"Фора","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Dunnes Stores":{"tags":{"name":"Dunnes Stores","shop":"supermarket"},"name":"Dunnes Stores","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Сільпо":{"tags":{"name":"Сільпо","shop":"supermarket"},"name":"Сільпо","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/マルエツ":{"tags":{"name":"マルエツ","shop":"supermarket"},"name":"マルエツ","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Piggly Wiggly":{"tags":{"name":"Piggly Wiggly","shop":"supermarket"},"name":"Piggly Wiggly","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Crai":{"tags":{"name":"Crai","shop":"supermarket"},"name":"Crai","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/El Árbol":{"tags":{"name":"El Árbol","shop":"supermarket"},"name":"El Árbol","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Centre Commercial E. Leclerc":{"tags":{"name":"Centre Commercial E. Leclerc","shop":"supermarket"},"name":"Centre Commercial E. Leclerc","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Foodland":{"tags":{"name":"Foodland","shop":"supermarket"},"name":"Foodland","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Super Brugsen":{"tags":{"name":"Super Brugsen","shop":"supermarket"},"name":"Super Brugsen","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Дикси":{"tags":{"name":"Дикси","shop":"supermarket"},"name":"Дикси","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Пятёрочка":{"tags":{"name":"Пятёрочка","shop":"supermarket"},"name":"Пятёрочка","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Publix":{"tags":{"name":"Publix","shop":"supermarket"},"name":"Publix","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Føtex":{"tags":{"name":"Føtex","shop":"supermarket"},"name":"Føtex","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/coop":{"tags":{"name":"coop","shop":"supermarket"},"name":"coop","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Coop Konsum":{"tags":{"name":"Coop Konsum","shop":"supermarket"},"name":"Coop Konsum","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Carrefour Contact":{"tags":{"name":"Carrefour Contact","shop":"supermarket"},"name":"Carrefour Contact","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/No Frills":{"tags":{"name":"No Frills","shop":"supermarket"},"name":"No Frills","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Plodine":{"tags":{"name":"Plodine","shop":"supermarket"},"name":"Plodine","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/ADEG":{"tags":{"name":"ADEG","shop":"supermarket"},"name":"ADEG","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Minipreço":{"tags":{"name":"Minipreço","shop":"supermarket"},"name":"Minipreço","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Biedronka":{"tags":{"name":"Biedronka","shop":"supermarket"},"name":"Biedronka","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Eurospin":{"tags":{"name":"Eurospin","shop":"supermarket"},"name":"Eurospin","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Семья":{"tags":{"name":"Семья","shop":"supermarket"},"name":"Семья","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Gadis":{"tags":{"name":"Gadis","shop":"supermarket"},"name":"Gadis","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Евроопт":{"tags":{"name":"Евроопт","shop":"supermarket"},"name":"Евроопт","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Квартал":{"tags":{"name":"Квартал","shop":"supermarket"},"name":"Квартал","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/New World":{"tags":{"name":"New World","shop":"supermarket"},"name":"New World","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Countdown":{"tags":{"name":"Countdown","shop":"supermarket"},"name":"Countdown","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Reliance Fresh":{"tags":{"name":"Reliance Fresh","shop":"supermarket"},"name":"Reliance Fresh","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Stokrotka":{"tags":{"name":"Stokrotka","shop":"supermarket"},"name":"Stokrotka","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Coop Jednota":{"tags":{"name":"Coop Jednota","shop":"supermarket"},"name":"Coop Jednota","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Fred Meyer":{"tags":{"name":"Fred Meyer","shop":"supermarket"},"name":"Fred Meyer","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Irma":{"tags":{"name":"Irma","shop":"supermarket"},"name":"Irma","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Continente":{"tags":{"name":"Continente","shop":"supermarket"},"name":"Continente","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Price Chopper":{"tags":{"name":"Price Chopper","shop":"supermarket"},"name":"Price Chopper","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Game":{"tags":{"name":"Game","shop":"supermarket"},"name":"Game","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Soriana":{"tags":{"name":"Soriana","shop":"supermarket"},"name":"Soriana","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Alimerka":{"tags":{"name":"Alimerka","shop":"supermarket"},"name":"Alimerka","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Piotr i Paweł":{"tags":{"name":"Piotr i Paweł","shop":"supermarket"},"name":"Piotr i Paweł","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Перекресток":{"tags":{"name":"Перекресток","shop":"supermarket"},"name":"Перекресток","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Maxima X":{"tags":{"name":"Maxima X","shop":"supermarket"},"name":"Maxima X","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Карусель":{"tags":{"name":"Карусель","shop":"supermarket"},"name":"Карусель","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/ALDI Nord":{"tags":{"name":"ALDI Nord","shop":"supermarket"},"name":"ALDI Nord","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Condis":{"tags":{"name":"Condis","shop":"supermarket"},"name":"Condis","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Sam's Club":{"tags":{"name":"Sam's Club","shop":"supermarket"},"name":"Sam's Club","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Копейка":{"tags":{"name":"Копейка","shop":"supermarket"},"name":"Копейка","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Géant Casino":{"tags":{"name":"Géant Casino","shop":"supermarket"},"name":"Géant Casino","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/ASDA":{"tags":{"name":"ASDA","shop":"supermarket"},"name":"ASDA","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Intermarche":{"tags":{"name":"Intermarche","shop":"supermarket"},"name":"Intermarche","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Stop & Shop":{"tags":{"name":"Stop & Shop","shop":"supermarket"},"name":"Stop & Shop","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Food Lion":{"tags":{"name":"Food Lion","shop":"supermarket"},"name":"Food Lion","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Harris Teeter":{"tags":{"name":"Harris Teeter","shop":"supermarket"},"name":"Harris Teeter","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Foodworks":{"tags":{"name":"Foodworks","shop":"supermarket"},"name":"Foodworks","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Polo Market":{"tags":{"name":"Polo Market","shop":"supermarket"},"name":"Polo Market","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Лента":{"tags":{"name":"Лента","shop":"supermarket"},"name":"Лента","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/西友 (SEIYU)":{"tags":{"name":"西友 (SEIYU)","shop":"supermarket"},"name":"西友 (SEIYU)","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/H-E-B":{"tags":{"name":"H-E-B","shop":"supermarket"},"name":"H-E-B","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Атак":{"tags":{"name":"Атак","shop":"supermarket"},"name":"Атак","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Полушка":{"tags":{"name":"Полушка","shop":"supermarket"},"name":"Полушка","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Extra":{"tags":{"name":"Extra","shop":"supermarket"},"name":"Extra","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Sigma":{"tags":{"name":"Sigma","shop":"supermarket"},"name":"Sigma","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/АТБ":{"tags":{"name":"АТБ","shop":"supermarket"},"name":"АТБ","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Bodega Aurrera":{"tags":{"name":"Bodega Aurrera","shop":"supermarket"},"name":"Bodega Aurrera","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Tesco Lotus":{"tags":{"name":"Tesco Lotus","shop":"supermarket"},"name":"Tesco Lotus","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Мария-Ра":{"tags":{"name":"Мария-Ра","shop":"supermarket"},"name":"Мария-Ра","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Магнолия":{"tags":{"name":"Магнолия","shop":"supermarket"},"name":"Магнолия","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Монетка":{"tags":{"name":"Монетка","shop":"supermarket"},"name":"Монетка","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Hy-Vee":{"tags":{"name":"Hy-Vee","shop":"supermarket"},"name":"Hy-Vee","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Walmart Supercenter":{"tags":{"name":"Walmart Supercenter","shop":"supermarket"},"name":"Walmart Supercenter","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Hannaford":{"tags":{"name":"Hannaford","shop":"supermarket"},"name":"Hannaford","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Wegmans":{"tags":{"name":"Wegmans","shop":"supermarket"},"name":"Wegmans","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/業務スーパー":{"tags":{"name":"業務スーパー","shop":"supermarket"},"name":"業務スーパー","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Norfa XL":{"tags":{"name":"Norfa XL","shop":"supermarket"},"name":"Norfa XL","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/ヨークマート (YorkMart)":{"tags":{"name":"ヨークマート (YorkMart)","shop":"supermarket"},"name":"ヨークマート (YorkMart)","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/supermarket/Leclerc Drive":{"tags":{"name":"Leclerc Drive","shop":"supermarket"},"name":"Leclerc Drive","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/electronics/Media Markt":{"tags":{"name":"Media Markt","shop":"electronics"},"name":"Media Markt","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/electronics/Maplin":{"tags":{"name":"Maplin","shop":"electronics"},"name":"Maplin","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/electronics/Best Buy":{"tags":{"name":"Best Buy","shop":"electronics"},"name":"Best Buy","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/electronics/Future Shop":{"tags":{"name":"Future Shop","shop":"electronics"},"name":"Future Shop","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/electronics/Saturn":{"tags":{"name":"Saturn","shop":"electronics"},"name":"Saturn","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/electronics/Currys":{"tags":{"name":"Currys","shop":"electronics"},"name":"Currys","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/electronics/Radio Shack":{"tags":{"name":"Radio Shack","shop":"electronics"},"name":"Radio Shack","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/electronics/Euronics":{"tags":{"name":"Euronics","shop":"electronics"},"name":"Euronics","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/electronics/Expert":{"tags":{"name":"Expert","shop":"electronics"},"name":"Expert","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/electronics/Эльдорадо":{"tags":{"name":"Эльдорадо","shop":"electronics"},"name":"Эльдорадо","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/electronics/Darty":{"tags":{"name":"Darty","shop":"electronics"},"name":"Darty","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/electronics/М.Видео":{"tags":{"name":"М.Видео","shop":"electronics"},"name":"М.Видео","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/electronics/ヤマダ電機":{"tags":{"name":"ヤマダ電機","shop":"electronics"},"name":"ヤマダ電機","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/McColl's":{"tags":{"name":"McColl's","shop":"convenience"},"name":"McColl's","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Tesco Express":{"tags":{"name":"Tesco Express","shop":"convenience"},"name":"Tesco Express","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/One Stop":{"tags":{"name":"One Stop","shop":"convenience"},"name":"One Stop","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Londis":{"tags":{"name":"Londis","shop":"convenience"},"name":"Londis","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/7-Eleven":{"tags":{"name":"7-Eleven","shop":"convenience"},"name":"7-Eleven","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Sale":{"tags":{"name":"Sale","shop":"convenience"},"name":"Sale","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Siwa":{"tags":{"name":"Siwa","shop":"convenience"},"name":"Siwa","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/COOP Jednota":{"tags":{"name":"COOP Jednota","shop":"convenience"},"name":"COOP Jednota","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Mac's":{"tags":{"name":"Mac's","shop":"convenience"},"name":"Mac's","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Alepa":{"tags":{"name":"Alepa","shop":"convenience"},"name":"Alepa","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Hasty Market":{"tags":{"name":"Hasty Market","shop":"convenience"},"name":"Hasty Market","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/K-Market":{"tags":{"name":"K-Market","shop":"convenience"},"name":"K-Market","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Costcutter":{"tags":{"name":"Costcutter","shop":"convenience"},"name":"Costcutter","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Valintatalo":{"tags":{"name":"Valintatalo","shop":"convenience"},"name":"Valintatalo","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Circle K":{"tags":{"name":"Circle K","shop":"convenience"},"name":"Circle K","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/セブンイレブン":{"tags":{"name":"セブンイレブン","name:en":"7-Eleven","shop":"convenience"},"name":"セブンイレブン","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/ローソン":{"tags":{"name":"ローソン","name:en":"LAWSON","shop":"convenience"},"name":"ローソン","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Petit Casino":{"tags":{"name":"Petit Casino","shop":"convenience"},"name":"Petit Casino","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Mace":{"tags":{"name":"Mace","shop":"convenience"},"name":"Mace","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Mini Market":{"tags":{"name":"Mini Market","shop":"convenience"},"name":"Mini Market","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Nisa Local":{"tags":{"name":"Nisa Local","shop":"convenience"},"name":"Nisa Local","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Dorfladen":{"tags":{"name":"Dorfladen","shop":"convenience"},"name":"Dorfladen","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Продукты":{"tags":{"name":"Продукты","shop":"convenience"},"name":"Продукты","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Mini Stop":{"tags":{"name":"Mini Stop","shop":"convenience"},"name":"Mini Stop","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/LAWSON":{"tags":{"name":"LAWSON","shop":"convenience"},"name":"LAWSON","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/デイリーヤマザキ":{"tags":{"name":"デイリーヤマザキ","shop":"convenience"},"name":"デイリーヤマザキ","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Надежда":{"tags":{"name":"Надежда","shop":"convenience"},"name":"Надежда","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Nisa":{"tags":{"name":"Nisa","shop":"convenience"},"name":"Nisa","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Premier":{"tags":{"name":"Premier","shop":"convenience"},"name":"Premier","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/ABC":{"tags":{"name":"ABC","shop":"convenience"},"name":"ABC","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/ミニストップ":{"tags":{"name":"ミニストップ","name:en":"MINISTOP","shop":"convenience"},"name":"ミニストップ","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/サンクス":{"tags":{"name":"サンクス","name:en":"sunkus","shop":"convenience"},"name":"サンクス","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/スリーエフ":{"tags":{"name":"スリーエフ","shop":"convenience"},"name":"スリーエフ","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/8 à Huit":{"tags":{"name":"8 à Huit","shop":"convenience"},"name":"8 à Huit","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Żabka":{"tags":{"name":"Żabka","shop":"convenience"},"name":"Żabka","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Almacen":{"tags":{"name":"Almacen","shop":"convenience"},"name":"Almacen","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Vival":{"tags":{"name":"Vival","shop":"convenience"},"name":"Vival","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/FamilyMart":{"tags":{"name":"FamilyMart","shop":"convenience"},"name":"FamilyMart","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/ファミリーマート":{"tags":{"name":"ファミリーマート","name:en":"FamilyMart","shop":"convenience"},"name":"ファミリーマート","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Sunkus":{"tags":{"name":"Sunkus","shop":"convenience"},"name":"Sunkus","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/セブンイレブン(Seven-Eleven)":{"tags":{"name":"セブンイレブン(Seven-Eleven)","shop":"convenience"},"name":"セブンイレブン(Seven-Eleven)","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Jednota":{"tags":{"name":"Jednota","shop":"convenience"},"name":"Jednota","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Магазин":{"tags":{"name":"Магазин","shop":"convenience"},"name":"Магазин","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Гастроном":{"tags":{"name":"Гастроном","shop":"convenience"},"name":"Гастроном","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Centra":{"tags":{"name":"Centra","shop":"convenience"},"name":"Centra","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/サークルK":{"tags":{"name":"サークルK","name:en":"Circle K","shop":"convenience"},"name":"サークルK","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Wawa":{"tags":{"name":"Wawa","shop":"convenience"},"name":"Wawa","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Proxi":{"tags":{"name":"Proxi","shop":"convenience"},"name":"Proxi","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Универсам":{"tags":{"name":"Универсам","shop":"convenience"},"name":"Универсам","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Groszek":{"tags":{"name":"Groszek","shop":"convenience"},"name":"Groszek","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Select":{"tags":{"name":"Select","shop":"convenience"},"name":"Select","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Večerka":{"tags":{"name":"Večerka","shop":"convenience"},"name":"Večerka","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Potraviny":{"tags":{"name":"Potraviny","shop":"convenience"},"name":"Potraviny","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Смак":{"tags":{"name":"Смак","shop":"convenience"},"name":"Смак","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Эконом":{"tags":{"name":"Эконом","shop":"convenience"},"name":"Эконом","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Березка":{"tags":{"name":"Березка","shop":"convenience"},"name":"Березка","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Społem":{"tags":{"name":"Społem","shop":"convenience"},"name":"Społem","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Cumberland Farms":{"tags":{"name":"Cumberland Farms","shop":"convenience"},"name":"Cumberland Farms","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Tesco Lotus Express":{"tags":{"name":"Tesco Lotus Express","shop":"convenience"},"name":"Tesco Lotus Express","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Kiosk":{"tags":{"name":"Kiosk","shop":"convenience"},"name":"Kiosk","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Sklep spożywczy":{"tags":{"name":"Sklep spożywczy","shop":"convenience"},"name":"Sklep spożywczy","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/24 часа":{"tags":{"name":"24 часа","shop":"convenience"},"name":"24 часа","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Минимаркет":{"tags":{"name":"Минимаркет","shop":"convenience"},"name":"Минимаркет","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Oxxo":{"tags":{"name":"Oxxo","shop":"convenience"},"name":"Oxxo","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/abc":{"tags":{"name":"abc","shop":"convenience"},"name":"abc","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/7/11":{"tags":{"name":"7/11","shop":"convenience"},"name":"7/11","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Stewart's":{"tags":{"name":"Stewart's","shop":"convenience"},"name":"Stewart's","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Продукти":{"tags":{"name":"Продукти","shop":"convenience"},"name":"Продукти","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/ローソンストア100 (LAWSON STORE 100)":{"tags":{"name":"ローソンストア100 (LAWSON STORE 100)","shop":"convenience"},"name":"ローソンストア100 (LAWSON STORE 100)","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Радуга":{"tags":{"name":"Радуга","shop":"convenience"},"name":"Радуга","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/ローソンストア100":{"tags":{"name":"ローソンストア100","shop":"convenience"},"name":"ローソンストア100","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/เซเว่นอีเลฟเว่น":{"tags":{"name":"เซเว่นอีเลฟเว่น","shop":"convenience"},"name":"เซเว่นอีเลฟเว่น","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Фортуна":{"tags":{"name":"Фортуна","shop":"convenience"},"name":"Фортуна","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Picard":{"tags":{"name":"Picard","shop":"convenience"},"name":"Picard","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Four Square":{"tags":{"name":"Four Square","shop":"convenience"},"name":"Four Square","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Визит":{"tags":{"name":"Визит","shop":"convenience"},"name":"Визит","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Авоська":{"tags":{"name":"Авоська","shop":"convenience"},"name":"Авоська","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Dollar General":{"tags":{"name":"Dollar General","shop":"convenience"},"name":"Dollar General","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Studenac":{"tags":{"name":"Studenac","shop":"convenience"},"name":"Studenac","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Central Convenience Store":{"tags":{"name":"Central Convenience Store","shop":"convenience"},"name":"Central Convenience Store","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/продукты":{"tags":{"name":"продукты","shop":"convenience"},"name":"продукты","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Кулинария":{"tags":{"name":"Кулинария","shop":"convenience"},"name":"Кулинария","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/全家":{"tags":{"name":"全家","shop":"convenience"},"name":"全家","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Мечта":{"tags":{"name":"Мечта","shop":"convenience"},"name":"Мечта","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Epicerie":{"tags":{"name":"Epicerie","shop":"convenience"},"name":"Epicerie","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Кировский":{"tags":{"name":"Кировский","shop":"convenience"},"name":"Кировский","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Food Mart":{"tags":{"name":"Food Mart","shop":"convenience"},"name":"Food Mart","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Delikatesy":{"tags":{"name":"Delikatesy","shop":"convenience"},"name":"Delikatesy","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/ポプラ":{"tags":{"name":"ポプラ","shop":"convenience"},"name":"ポプラ","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Lewiatan":{"tags":{"name":"Lewiatan","shop":"convenience"},"name":"Lewiatan","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Продуктовый магазин":{"tags":{"name":"Продуктовый магазин","shop":"convenience"},"name":"Продуктовый магазин","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Продуктовый":{"tags":{"name":"Продуктовый","shop":"convenience"},"name":"Продуктовый","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/セイコーマート (Seicomart)":{"tags":{"name":"セイコーマート (Seicomart)","shop":"convenience"},"name":"セイコーマート (Seicomart)","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Виктория":{"tags":{"name":"Виктория","shop":"convenience"},"name":"Виктория","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Весна":{"tags":{"name":"Весна","shop":"convenience"},"name":"Весна","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Mini Market Non-Stop":{"tags":{"name":"Mini Market Non-Stop","shop":"convenience"},"name":"Mini Market Non-Stop","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Копеечка":{"tags":{"name":"Копеечка","shop":"convenience"},"name":"Копеечка","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Royal Farms":{"tags":{"name":"Royal Farms","shop":"convenience"},"name":"Royal Farms","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Alfamart":{"tags":{"name":"Alfamart","shop":"convenience"},"name":"Alfamart","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Indomaret":{"tags":{"name":"Indomaret","shop":"convenience"},"name":"Indomaret","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/магазин":{"tags":{"name":"магазин","shop":"convenience"},"name":"магазин","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/全家便利商店":{"tags":{"name":"全家便利商店","shop":"convenience"},"name":"全家便利商店","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Boutique":{"tags":{"name":"Boutique","shop":"convenience"},"name":"Boutique","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/მარკეტი (Market)":{"tags":{"name":"მარკეტი (Market)","shop":"convenience"},"name":"მარკეტი (Market)","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/convenience/Stores":{"tags":{"name":"Stores","shop":"convenience"},"name":"Stores","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/chemist/dm":{"tags":{"name":"dm","shop":"chemist"},"name":"dm","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/chemist/Müller":{"tags":{"name":"Müller","shop":"chemist"},"name":"Müller","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/chemist/Schlecker":{"tags":{"name":"Schlecker","shop":"chemist"},"name":"Schlecker","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/chemist/Etos":{"tags":{"name":"Etos","shop":"chemist"},"name":"Etos","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/chemist/Bipa":{"tags":{"name":"Bipa","shop":"chemist"},"name":"Bipa","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/chemist/Rossmann":{"tags":{"name":"Rossmann","shop":"chemist"},"name":"Rossmann","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/chemist/DM Drogeriemarkt":{"tags":{"name":"DM Drogeriemarkt","shop":"chemist"},"name":"DM Drogeriemarkt","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/chemist/Ihr Platz":{"tags":{"name":"Ihr Platz","shop":"chemist"},"name":"Ihr Platz","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/chemist/Douglas":{"tags":{"name":"Douglas","shop":"chemist"},"name":"Douglas","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/chemist/Kruidvat":{"tags":{"name":"Kruidvat","shop":"chemist"},"name":"Kruidvat","icon":"grocery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/car_repair/Kwik Fit":{"tags":{"name":"Kwik Fit","shop":"car_repair"},"name":"Kwik Fit","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/car_repair/ATU":{"tags":{"name":"ATU","shop":"car_repair"},"name":"ATU","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/car_repair/Midas":{"tags":{"name":"Midas","shop":"car_repair"},"name":"Midas","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/car_repair/Feu Vert":{"tags":{"name":"Feu Vert","shop":"car_repair"},"name":"Feu Vert","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/car_repair/Norauto":{"tags":{"name":"Norauto","shop":"car_repair"},"name":"Norauto","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/car_repair/Speedy":{"tags":{"name":"Speedy","shop":"car_repair"},"name":"Speedy","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/car_repair/Pit Stop":{"tags":{"name":"Pit Stop","shop":"car_repair"},"name":"Pit Stop","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/car_repair/Jiffy Lube":{"tags":{"name":"Jiffy Lube","shop":"car_repair"},"name":"Jiffy Lube","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/car_repair/Шиномонтаж":{"tags":{"name":"Шиномонтаж","shop":"car_repair"},"name":"Шиномонтаж","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/car_repair/СТО":{"tags":{"name":"СТО","shop":"car_repair"},"name":"СТО","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/car_repair/O'Reilly Auto Parts":{"tags":{"name":"O'Reilly Auto Parts","shop":"car_repair"},"name":"O'Reilly Auto Parts","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/car_repair/Carglass":{"tags":{"name":"Carglass","shop":"car_repair"},"name":"Carglass","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/car_repair/шиномонтаж":{"tags":{"name":"шиномонтаж","shop":"car_repair"},"name":"шиномонтаж","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/car_repair/Euromaster":{"tags":{"name":"Euromaster","shop":"car_repair"},"name":"Euromaster","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/car_repair/Firestone":{"tags":{"name":"Firestone","shop":"car_repair"},"name":"Firestone","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/car_repair/Автосервис":{"tags":{"name":"Автосервис","shop":"car_repair"},"name":"Автосервис","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/car_repair/Advance Auto Parts":{"tags":{"name":"Advance Auto Parts","shop":"car_repair"},"name":"Advance Auto Parts","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/car_repair/Roady":{"tags":{"name":"Roady","shop":"car_repair"},"name":"Roady","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/furniture/IKEA":{"tags":{"name":"IKEA","shop":"furniture"},"name":"IKEA","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/furniture/Jysk":{"tags":{"name":"Jysk","shop":"furniture"},"name":"Jysk","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/furniture/Roller":{"tags":{"name":"Roller","shop":"furniture"},"name":"Roller","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/furniture/Dänisches Bettenlager":{"tags":{"name":"Dänisches Bettenlager","shop":"furniture"},"name":"Dänisches Bettenlager","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/furniture/Conforama":{"tags":{"name":"Conforama","shop":"furniture"},"name":"Conforama","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/furniture/Matratzen Concord":{"tags":{"name":"Matratzen Concord","shop":"furniture"},"name":"Matratzen Concord","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/furniture/Мебель":{"tags":{"name":"Мебель","shop":"furniture"},"name":"Мебель","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/furniture/But":{"tags":{"name":"But","shop":"furniture"},"name":"But","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Hornbach":{"tags":{"name":"Hornbach","shop":"doityourself"},"name":"Hornbach","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/B&Q":{"tags":{"name":"B&Q","shop":"doityourself"},"name":"B&Q","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Hubo":{"tags":{"name":"Hubo","shop":"doityourself"},"name":"Hubo","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Mr Bricolage":{"tags":{"name":"Mr Bricolage","shop":"doityourself"},"name":"Mr Bricolage","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Gamma":{"tags":{"name":"Gamma","shop":"doityourself"},"name":"Gamma","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/OBI":{"tags":{"name":"OBI","shop":"doityourself"},"name":"OBI","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Lowes":{"tags":{"name":"Lowes","shop":"doityourself"},"name":"Lowes","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Wickes":{"tags":{"name":"Wickes","shop":"doityourself"},"name":"Wickes","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Hagebau":{"tags":{"name":"Hagebau","shop":"doityourself"},"name":"Hagebau","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Max Bahr":{"tags":{"name":"Max Bahr","shop":"doityourself"},"name":"Max Bahr","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Castorama":{"tags":{"name":"Castorama","shop":"doityourself"},"name":"Castorama","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Rona":{"tags":{"name":"Rona","shop":"doityourself"},"name":"Rona","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Home Depot":{"tags":{"name":"Home Depot","shop":"doityourself"},"name":"Home Depot","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Toom Baumarkt":{"tags":{"name":"Toom Baumarkt","shop":"doityourself"},"name":"Toom Baumarkt","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Homebase":{"tags":{"name":"Homebase","shop":"doityourself"},"name":"Homebase","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Baumax":{"tags":{"name":"Baumax","shop":"doityourself"},"name":"Baumax","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Lagerhaus":{"tags":{"name":"Lagerhaus","shop":"doityourself"},"name":"Lagerhaus","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Bauhaus":{"tags":{"name":"Bauhaus","shop":"doityourself"},"name":"Bauhaus","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Canadian Tire":{"tags":{"name":"Canadian Tire","shop":"doityourself"},"name":"Canadian Tire","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Leroy Merlin":{"tags":{"name":"Leroy Merlin","shop":"doityourself"},"name":"Leroy Merlin","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Hellweg":{"tags":{"name":"Hellweg","shop":"doityourself"},"name":"Hellweg","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Brico":{"tags":{"name":"Brico","shop":"doityourself"},"name":"Brico","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Bricomarché":{"tags":{"name":"Bricomarché","shop":"doityourself"},"name":"Bricomarché","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Toom":{"tags":{"name":"Toom","shop":"doityourself"},"name":"Toom","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Hagebaumarkt":{"tags":{"name":"Hagebaumarkt","shop":"doityourself"},"name":"Hagebaumarkt","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Praktiker":{"tags":{"name":"Praktiker","shop":"doityourself"},"name":"Praktiker","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Menards":{"tags":{"name":"Menards","shop":"doityourself"},"name":"Menards","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Weldom":{"tags":{"name":"Weldom","shop":"doityourself"},"name":"Weldom","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Bunnings Warehouse":{"tags":{"name":"Bunnings Warehouse","shop":"doityourself"},"name":"Bunnings Warehouse","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Ace Hardware":{"tags":{"name":"Ace Hardware","shop":"doityourself"},"name":"Ace Hardware","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Home Hardware":{"tags":{"name":"Home Hardware","shop":"doityourself"},"name":"Home Hardware","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Стройматериалы":{"tags":{"name":"Стройматериалы","shop":"doityourself"},"name":"Стройматериалы","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Bricorama":{"tags":{"name":"Bricorama","shop":"doityourself"},"name":"Bricorama","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/doityourself/Point P":{"tags":{"name":"Point P","shop":"doityourself"},"name":"Point P","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/stationery/Staples":{"tags":{"name":"Staples","shop":"stationery"},"name":"Staples","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/stationery/McPaper":{"tags":{"name":"McPaper","shop":"stationery"},"name":"McPaper","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/stationery/Office Depot":{"tags":{"name":"Office Depot","shop":"stationery"},"name":"Office Depot","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/stationery/Канцтовары":{"tags":{"name":"Канцтовары","shop":"stationery"},"name":"Канцтовары","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/car/Skoda":{"tags":{"name":"Skoda","shop":"car"},"name":"Skoda","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/car/BMW":{"tags":{"name":"BMW","shop":"car"},"name":"BMW","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/car/Citroen":{"tags":{"name":"Citroen","shop":"car"},"name":"Citroen","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/car/Renault":{"tags":{"name":"Renault","shop":"car"},"name":"Renault","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/car/Mercedes-Benz":{"tags":{"name":"Mercedes-Benz","shop":"car"},"name":"Mercedes-Benz","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/car/Volvo":{"tags":{"name":"Volvo","shop":"car"},"name":"Volvo","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/car/Ford":{"tags":{"name":"Ford","shop":"car"},"name":"Ford","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/car/Volkswagen":{"tags":{"name":"Volkswagen","shop":"car"},"name":"Volkswagen","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/car/Mazda":{"tags":{"name":"Mazda","shop":"car"},"name":"Mazda","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/car/Mitsubishi":{"tags":{"name":"Mitsubishi","shop":"car"},"name":"Mitsubishi","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/car/Fiat":{"tags":{"name":"Fiat","shop":"car"},"name":"Fiat","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/car/Автозапчасти":{"tags":{"name":"Автозапчасти","shop":"car"},"name":"Автозапчасти","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/car/Opel":{"tags":{"name":"Opel","shop":"car"},"name":"Opel","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/car/Audi":{"tags":{"name":"Audi","shop":"car"},"name":"Audi","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/car/Toyota":{"tags":{"name":"Toyota","shop":"car"},"name":"Toyota","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/car/Nissan":{"tags":{"name":"Nissan","shop":"car"},"name":"Nissan","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/car/Suzuki":{"tags":{"name":"Suzuki","shop":"car"},"name":"Suzuki","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/car/Honda":{"tags":{"name":"Honda","shop":"car"},"name":"Honda","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/car/Peugeot":{"tags":{"name":"Peugeot","shop":"car"},"name":"Peugeot","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/car/Hyundai":{"tags":{"name":"Hyundai","shop":"car"},"name":"Hyundai","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/car/Subaru":{"tags":{"name":"Subaru","shop":"car"},"name":"Subaru","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/car/Chevrolet":{"tags":{"name":"Chevrolet","shop":"car"},"name":"Chevrolet","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/car/Автомагазин":{"tags":{"name":"Автомагазин","shop":"car"},"name":"Автомагазин","icon":"car","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","second_hand"],"suggestion":true},"shop/clothes/Matalan":{"tags":{"name":"Matalan","shop":"clothes"},"name":"Matalan","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/KiK":{"tags":{"name":"KiK","shop":"clothes"},"name":"KiK","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/H&M":{"tags":{"name":"H&M","shop":"clothes"},"name":"H&M","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Urban Outfitters":{"tags":{"name":"Urban Outfitters","shop":"clothes"},"name":"Urban Outfitters","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Vögele":{"tags":{"name":"Vögele","shop":"clothes"},"name":"Vögele","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Zeeman":{"tags":{"name":"Zeeman","shop":"clothes"},"name":"Zeeman","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Takko":{"tags":{"name":"Takko","shop":"clothes"},"name":"Takko","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/C&A":{"tags":{"name":"C&A","shop":"clothes"},"name":"C&A","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Zara":{"tags":{"name":"Zara","shop":"clothes"},"name":"Zara","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Vero Moda":{"tags":{"name":"Vero Moda","shop":"clothes"},"name":"Vero Moda","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/NKD":{"tags":{"name":"NKD","shop":"clothes"},"name":"NKD","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Ernsting's family":{"tags":{"name":"Ernsting's family","shop":"clothes"},"name":"Ernsting's family","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Winners":{"tags":{"name":"Winners","shop":"clothes"},"name":"Winners","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/River Island":{"tags":{"name":"River Island","shop":"clothes"},"name":"River Island","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Next":{"tags":{"name":"Next","shop":"clothes"},"name":"Next","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Gap":{"tags":{"name":"Gap","shop":"clothes"},"name":"Gap","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Adidas":{"tags":{"name":"Adidas","shop":"clothes"},"name":"Adidas","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Mr Price":{"tags":{"name":"Mr Price","shop":"clothes"},"name":"Mr Price","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Pep":{"tags":{"name":"Pep","shop":"clothes"},"name":"Pep","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Edgars":{"tags":{"name":"Edgars","shop":"clothes"},"name":"Edgars","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Ackermans":{"tags":{"name":"Ackermans","shop":"clothes"},"name":"Ackermans","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Truworths":{"tags":{"name":"Truworths","shop":"clothes"},"name":"Truworths","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Ross":{"tags":{"name":"Ross","shop":"clothes"},"name":"Ross","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Burton":{"tags":{"name":"Burton","shop":"clothes"},"name":"Burton","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Dorothy Perkins":{"tags":{"name":"Dorothy Perkins","shop":"clothes"},"name":"Dorothy Perkins","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Lindex":{"tags":{"name":"Lindex","shop":"clothes"},"name":"Lindex","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/s.Oliver":{"tags":{"name":"s.Oliver","shop":"clothes"},"name":"s.Oliver","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Cecil":{"tags":{"name":"Cecil","shop":"clothes"},"name":"Cecil","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Dress Barn":{"tags":{"name":"Dress Barn","shop":"clothes"},"name":"Dress Barn","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Old Navy":{"tags":{"name":"Old Navy","shop":"clothes"},"name":"Old Navy","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Jack & Jones":{"tags":{"name":"Jack & Jones","shop":"clothes"},"name":"Jack & Jones","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Pimkie":{"tags":{"name":"Pimkie","shop":"clothes"},"name":"Pimkie","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Esprit":{"tags":{"name":"Esprit","shop":"clothes"},"name":"Esprit","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Primark":{"tags":{"name":"Primark","shop":"clothes"},"name":"Primark","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Bonita":{"tags":{"name":"Bonita","shop":"clothes"},"name":"Bonita","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Mexx":{"tags":{"name":"Mexx","shop":"clothes"},"name":"Mexx","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Gerry Weber":{"tags":{"name":"Gerry Weber","shop":"clothes"},"name":"Gerry Weber","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Tally Weijl":{"tags":{"name":"Tally Weijl","shop":"clothes"},"name":"Tally Weijl","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Mango":{"tags":{"name":"Mango","shop":"clothes"},"name":"Mango","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/TK Maxx":{"tags":{"name":"TK Maxx","shop":"clothes"},"name":"TK Maxx","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Benetton":{"tags":{"name":"Benetton","shop":"clothes"},"name":"Benetton","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Ulla Popken":{"tags":{"name":"Ulla Popken","shop":"clothes"},"name":"Ulla Popken","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/AWG":{"tags":{"name":"AWG","shop":"clothes"},"name":"AWG","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Tommy Hilfiger":{"tags":{"name":"Tommy Hilfiger","shop":"clothes"},"name":"Tommy Hilfiger","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/New Yorker":{"tags":{"name":"New Yorker","shop":"clothes"},"name":"New Yorker","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Orsay":{"tags":{"name":"Orsay","shop":"clothes"},"name":"Orsay","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Jeans Fritz":{"tags":{"name":"Jeans Fritz","shop":"clothes"},"name":"Jeans Fritz","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Charles Vögele":{"tags":{"name":"Charles Vögele","shop":"clothes"},"name":"Charles Vögele","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/New Look":{"tags":{"name":"New Look","shop":"clothes"},"name":"New Look","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Lacoste":{"tags":{"name":"Lacoste","shop":"clothes"},"name":"Lacoste","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Etam":{"tags":{"name":"Etam","shop":"clothes"},"name":"Etam","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Kiabi":{"tags":{"name":"Kiabi","shop":"clothes"},"name":"Kiabi","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Jack Wolfskin":{"tags":{"name":"Jack Wolfskin","shop":"clothes"},"name":"Jack Wolfskin","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/American Apparel":{"tags":{"name":"American Apparel","shop":"clothes"},"name":"American Apparel","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Men's Wearhouse":{"tags":{"name":"Men's Wearhouse","shop":"clothes"},"name":"Men's Wearhouse","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Intimissimi":{"tags":{"name":"Intimissimi","shop":"clothes"},"name":"Intimissimi","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/United Colors of Benetton":{"tags":{"name":"United Colors of Benetton","shop":"clothes"},"name":"United Colors of Benetton","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Jules":{"tags":{"name":"Jules","shop":"clothes"},"name":"Jules","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Second Hand":{"tags":{"name":"Second Hand","shop":"clothes"},"name":"Second Hand","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/AOKI":{"tags":{"name":"AOKI","shop":"clothes"},"name":"AOKI","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Calzedonia":{"tags":{"name":"Calzedonia","shop":"clothes"},"name":"Calzedonia","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/洋服の青山":{"tags":{"name":"洋服の青山","shop":"clothes"},"name":"洋服の青山","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Levi's":{"tags":{"name":"Levi's","shop":"clothes"},"name":"Levi's","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Celio":{"tags":{"name":"Celio","shop":"clothes"},"name":"Celio","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/TJ Maxx":{"tags":{"name":"TJ Maxx","shop":"clothes"},"name":"TJ Maxx","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Promod":{"tags":{"name":"Promod","shop":"clothes"},"name":"Promod","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Street One":{"tags":{"name":"Street One","shop":"clothes"},"name":"Street One","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/ユニクロ":{"tags":{"name":"ユニクロ","shop":"clothes"},"name":"ユニクロ","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Banana Republic":{"tags":{"name":"Banana Republic","shop":"clothes"},"name":"Banana Republic","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Одежда":{"tags":{"name":"Одежда","shop":"clothes"},"name":"Одежда","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Marshalls":{"tags":{"name":"Marshalls","shop":"clothes"},"name":"Marshalls","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/La Halle":{"tags":{"name":"La Halle","shop":"clothes"},"name":"La Halle","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/Peacocks":{"tags":{"name":"Peacocks","shop":"clothes"},"name":"Peacocks","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/clothes/しまむら":{"tags":{"name":"しまむら","shop":"clothes"},"name":"しまむら","icon":"clothing-store","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/books/Bruna":{"tags":{"name":"Bruna","shop":"books"},"name":"Bruna","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/books/Waterstones":{"tags":{"name":"Waterstones","shop":"books"},"name":"Waterstones","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/books/Libro":{"tags":{"name":"Libro","shop":"books"},"name":"Libro","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/books/Barnes & Noble":{"tags":{"name":"Barnes & Noble","shop":"books"},"name":"Barnes & Noble","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/books/Weltbild":{"tags":{"name":"Weltbild","shop":"books"},"name":"Weltbild","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/books/Thalia":{"tags":{"name":"Thalia","shop":"books"},"name":"Thalia","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/books/Книги":{"tags":{"name":"Книги","shop":"books"},"name":"Книги","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/department_store/Debenhams":{"tags":{"name":"Debenhams","shop":"department_store"},"name":"Debenhams","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/department_store/Karstadt":{"tags":{"name":"Karstadt","shop":"department_store"},"name":"Karstadt","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/department_store/Kmart":{"tags":{"name":"Kmart","shop":"department_store"},"name":"Kmart","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/department_store/Target":{"tags":{"name":"Target","shop":"department_store"},"name":"Target","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/department_store/Galeria Kaufhof":{"tags":{"name":"Galeria Kaufhof","shop":"department_store"},"name":"Galeria Kaufhof","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/department_store/Marks & Spencer":{"tags":{"name":"Marks & Spencer","shop":"department_store"},"name":"Marks & Spencer","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/department_store/Big W":{"tags":{"name":"Big W","shop":"department_store"},"name":"Big W","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/department_store/Woolworth":{"tags":{"name":"Woolworth","shop":"department_store"},"name":"Woolworth","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/department_store/Универмаг":{"tags":{"name":"Универмаг","shop":"department_store"},"name":"Универмаг","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/department_store/Sears":{"tags":{"name":"Sears","shop":"department_store"},"name":"Sears","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/department_store/Kohl's":{"tags":{"name":"Kohl's","shop":"department_store"},"name":"Kohl's","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/department_store/Macy's":{"tags":{"name":"Macy's","shop":"department_store"},"name":"Macy's","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/department_store/JCPenney":{"tags":{"name":"JCPenney","shop":"department_store"},"name":"JCPenney","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/alcohol/Alko":{"tags":{"name":"Alko","shop":"alcohol"},"name":"Alko","icon":"alcohol-shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"shop/alcohol/The Beer Store":{"tags":{"name":"The Beer Store","shop":"alcohol"},"name":"The Beer Store","icon":"alcohol-shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"shop/alcohol/Systembolaget":{"tags":{"name":"Systembolaget","shop":"alcohol"},"name":"Systembolaget","icon":"alcohol-shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"shop/alcohol/LCBO":{"tags":{"name":"LCBO","shop":"alcohol"},"name":"LCBO","icon":"alcohol-shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"shop/alcohol/Ароматный мир":{"tags":{"name":"Ароматный мир","shop":"alcohol"},"name":"Ароматный мир","icon":"alcohol-shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"shop/alcohol/Bargain Booze":{"tags":{"name":"Bargain Booze","shop":"alcohol"},"name":"Bargain Booze","icon":"alcohol-shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"shop/alcohol/Nicolas":{"tags":{"name":"Nicolas","shop":"alcohol"},"name":"Nicolas","icon":"alcohol-shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"shop/alcohol/BWS":{"tags":{"name":"BWS","shop":"alcohol"},"name":"BWS","icon":"alcohol-shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"shop/alcohol/Botilleria":{"tags":{"name":"Botilleria","shop":"alcohol"},"name":"Botilleria","icon":"alcohol-shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"shop/alcohol/SAQ":{"tags":{"name":"SAQ","shop":"alcohol"},"name":"SAQ","icon":"alcohol-shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"shop/alcohol/Gall & Gall":{"tags":{"name":"Gall & Gall","shop":"alcohol"},"name":"Gall & Gall","icon":"alcohol-shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"shop/alcohol/Живое пиво":{"tags":{"name":"Живое пиво","shop":"alcohol"},"name":"Живое пиво","icon":"alcohol-shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours","drive_through"],"suggestion":true},"shop/bakery/Kamps":{"tags":{"name":"Kamps","shop":"bakery"},"name":"Kamps","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Banette":{"tags":{"name":"Banette","shop":"bakery"},"name":"Banette","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Bäckerei Schmidt":{"tags":{"name":"Bäckerei Schmidt","shop":"bakery"},"name":"Bäckerei Schmidt","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Anker":{"tags":{"name":"Anker","shop":"bakery"},"name":"Anker","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Hofpfisterei":{"tags":{"name":"Hofpfisterei","shop":"bakery"},"name":"Hofpfisterei","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Greggs":{"tags":{"name":"Greggs","shop":"bakery"},"name":"Greggs","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Oebel":{"tags":{"name":"Oebel","shop":"bakery"},"name":"Oebel","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Boulangerie":{"tags":{"name":"Boulangerie","shop":"bakery"},"name":"Boulangerie","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Stadtbäckerei":{"tags":{"name":"Stadtbäckerei","shop":"bakery"},"name":"Stadtbäckerei","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Steinecke":{"tags":{"name":"Steinecke","shop":"bakery"},"name":"Steinecke","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Ihle":{"tags":{"name":"Ihle","shop":"bakery"},"name":"Ihle","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Goldilocks":{"tags":{"name":"Goldilocks","shop":"bakery"},"name":"Goldilocks","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Dat Backhus":{"tags":{"name":"Dat Backhus","shop":"bakery"},"name":"Dat Backhus","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/K&U":{"tags":{"name":"K&U","shop":"bakery"},"name":"K&U","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Der Beck":{"tags":{"name":"Der Beck","shop":"bakery"},"name":"Der Beck","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Thürmann":{"tags":{"name":"Thürmann","shop":"bakery"},"name":"Thürmann","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Backwerk":{"tags":{"name":"Backwerk","shop":"bakery"},"name":"Backwerk","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Schäfer's":{"tags":{"name":"Schäfer's","shop":"bakery"},"name":"Schäfer's","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Panaderia":{"tags":{"name":"Panaderia","shop":"bakery"},"name":"Panaderia","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Goeken backen":{"tags":{"name":"Goeken backen","shop":"bakery"},"name":"Goeken backen","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Stadtbäckerei Junge":{"tags":{"name":"Stadtbäckerei Junge","shop":"bakery"},"name":"Stadtbäckerei Junge","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Boulangerie Patisserie":{"tags":{"name":"Boulangerie Patisserie","shop":"bakery"},"name":"Boulangerie Patisserie","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Paul":{"tags":{"name":"Paul","shop":"bakery"},"name":"Paul","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Хлеб":{"tags":{"name":"Хлеб","shop":"bakery"},"name":"Хлеб","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Пекарня":{"tags":{"name":"Пекарня","shop":"bakery"},"name":"Пекарня","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/bakery/Кулиничи":{"tags":{"name":"Кулиничи","shop":"bakery"},"name":"Кулиничи","icon":"bakery","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/sports/Sports Direct":{"tags":{"name":"Sports Direct","shop":"sports"},"name":"Sports Direct","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/sports/Decathlon":{"tags":{"name":"Decathlon","shop":"sports"},"name":"Decathlon","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/sports/Intersport":{"tags":{"name":"Intersport","shop":"sports"},"name":"Intersport","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/sports/Sports Authority":{"tags":{"name":"Sports Authority","shop":"sports"},"name":"Sports Authority","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/sports/Спортмастер":{"tags":{"name":"Спортмастер","shop":"sports"},"name":"Спортмастер","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/sports/Sport 2000":{"tags":{"name":"Sport 2000","shop":"sports"},"name":"Sport 2000","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/sports/Dick's Sporting Goods":{"tags":{"name":"Dick's Sporting Goods","shop":"sports"},"name":"Dick's Sporting Goods","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/variety_store/Tedi":{"tags":{"name":"Tedi","shop":"variety_store"},"name":"Tedi","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/variety_store/Dollarama":{"tags":{"name":"Dollarama","shop":"variety_store"},"name":"Dollarama","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/variety_store/Family Dollar":{"tags":{"name":"Family Dollar","shop":"variety_store"},"name":"Family Dollar","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/variety_store/Dollar Tree":{"tags":{"name":"Dollar Tree","shop":"variety_store"},"name":"Dollar Tree","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/pet/Fressnapf":{"tags":{"name":"Fressnapf","shop":"pet"},"name":"Fressnapf","icon":"dog-park","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/pet/PetSmart":{"tags":{"name":"PetSmart","shop":"pet"},"name":"PetSmart","icon":"dog-park","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/pet/Das Futterhaus":{"tags":{"name":"Das Futterhaus","shop":"pet"},"name":"Das Futterhaus","icon":"dog-park","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/pet/Pets at Home":{"tags":{"name":"Pets at Home","shop":"pet"},"name":"Pets at Home","icon":"dog-park","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/pet/Petco":{"tags":{"name":"Petco","shop":"pet"},"name":"Petco","icon":"dog-park","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/pet/Зоомагазин":{"tags":{"name":"Зоомагазин","shop":"pet"},"name":"Зоомагазин","icon":"dog-park","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/shoes/Deichmann":{"tags":{"name":"Deichmann","shop":"shoes"},"name":"Deichmann","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/shoes/Reno":{"tags":{"name":"Reno","shop":"shoes"},"name":"Reno","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/shoes/Ecco":{"tags":{"name":"Ecco","shop":"shoes"},"name":"Ecco","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/shoes/Clarks":{"tags":{"name":"Clarks","shop":"shoes"},"name":"Clarks","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/shoes/La Halle aux Chaussures":{"tags":{"name":"La Halle aux Chaussures","shop":"shoes"},"name":"La Halle aux Chaussures","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/shoes/Brantano":{"tags":{"name":"Brantano","shop":"shoes"},"name":"Brantano","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/shoes/Geox":{"tags":{"name":"Geox","shop":"shoes"},"name":"Geox","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/shoes/Salamander":{"tags":{"name":"Salamander","shop":"shoes"},"name":"Salamander","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/shoes/Обувь":{"tags":{"name":"Обувь","shop":"shoes"},"name":"Обувь","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/shoes/Payless Shoe Source":{"tags":{"name":"Payless Shoe Source","shop":"shoes"},"name":"Payless Shoe Source","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/shoes/Famous Footwear":{"tags":{"name":"Famous Footwear","shop":"shoes"},"name":"Famous Footwear","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/shoes/Quick Schuh":{"tags":{"name":"Quick Schuh","shop":"shoes"},"name":"Quick Schuh","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/shoes/Shoe Zone":{"tags":{"name":"Shoe Zone","shop":"shoes"},"name":"Shoe Zone","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/shoes/Foot Locker":{"tags":{"name":"Foot Locker","shop":"shoes"},"name":"Foot Locker","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/shoes/Bata":{"tags":{"name":"Bata","shop":"shoes"},"name":"Bata","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/shoes/ЦентрОбувь":{"tags":{"name":"ЦентрОбувь","shop":"shoes"},"name":"ЦентрОбувь","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/toys/La Grande Récré":{"tags":{"name":"La Grande Récré","shop":"toys"},"name":"La Grande Récré","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/toys/Toys R Us":{"tags":{"name":"Toys R Us","shop":"toys"},"name":"Toys R Us","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/toys/Intertoys":{"tags":{"name":"Intertoys","shop":"toys"},"name":"Intertoys","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/toys/Детский мир":{"tags":{"name":"Детский мир","shop":"toys"},"name":"Детский мир","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/toys/Игрушки":{"tags":{"name":"Игрушки","shop":"toys"},"name":"Игрушки","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/travel_agency/Flight Centre":{"tags":{"name":"Flight Centre","shop":"travel_agency"},"name":"Flight Centre","icon":"suitcase","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/travel_agency/Thomas Cook":{"tags":{"name":"Thomas Cook","shop":"travel_agency"},"name":"Thomas Cook","icon":"suitcase","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/jewelry/Bijou Brigitte":{"tags":{"name":"Bijou Brigitte","shop":"jewelry"},"name":"Bijou Brigitte","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/jewelry/Christ":{"tags":{"name":"Christ","shop":"jewelry"},"name":"Christ","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/jewelry/Swarovski":{"tags":{"name":"Swarovski","shop":"jewelry"},"name":"Swarovski","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/optician/Fielmann":{"tags":{"name":"Fielmann","shop":"optician"},"name":"Fielmann","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/optician/Apollo Optik":{"tags":{"name":"Apollo Optik","shop":"optician"},"name":"Apollo Optik","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/optician/Vision Express":{"tags":{"name":"Vision Express","shop":"optician"},"name":"Vision Express","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/optician/Оптика":{"tags":{"name":"Оптика","shop":"optician"},"name":"Оптика","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/optician/Optic 2000":{"tags":{"name":"Optic 2000","shop":"optician"},"name":"Optic 2000","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/optician/Alain Afflelou":{"tags":{"name":"Alain Afflelou","shop":"optician"},"name":"Alain Afflelou","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/optician/Specsavers":{"tags":{"name":"Specsavers","shop":"optician"},"name":"Specsavers","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/optician/Krys":{"tags":{"name":"Krys","shop":"optician"},"name":"Krys","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/optician/Atol":{"tags":{"name":"Atol","shop":"optician"},"name":"Atol","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/video/Blockbuster":{"tags":{"name":"Blockbuster","shop":"video"},"name":"Blockbuster","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/video/World of Video":{"tags":{"name":"World of Video","shop":"video"},"name":"World of Video","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/Билайн":{"tags":{"name":"Билайн","shop":"mobile_phone"},"name":"Билайн","icon":"mobilephone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/ソフトバンクショップ (SoftBank shop)":{"tags":{"name":"ソフトバンクショップ (SoftBank shop)","shop":"mobile_phone"},"name":"ソフトバンクショップ (SoftBank shop)","icon":"mobilephone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/Vodafone":{"tags":{"name":"Vodafone","shop":"mobile_phone"},"name":"Vodafone","icon":"mobilephone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/O2":{"tags":{"name":"O2","shop":"mobile_phone"},"name":"O2","icon":"mobilephone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/Carphone Warehouse":{"tags":{"name":"Carphone Warehouse","shop":"mobile_phone"},"name":"Carphone Warehouse","icon":"mobilephone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/Orange":{"tags":{"name":"Orange","shop":"mobile_phone"},"name":"Orange","icon":"mobilephone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/Verizon Wireless":{"tags":{"name":"Verizon Wireless","shop":"mobile_phone"},"name":"Verizon Wireless","icon":"mobilephone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/Sprint":{"tags":{"name":"Sprint","shop":"mobile_phone"},"name":"Sprint","icon":"mobilephone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/T-Mobile":{"tags":{"name":"T-Mobile","shop":"mobile_phone"},"name":"T-Mobile","icon":"mobilephone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/МТС":{"tags":{"name":"МТС","shop":"mobile_phone"},"name":"МТС","icon":"mobilephone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/Евросеть":{"tags":{"name":"Евросеть","shop":"mobile_phone"},"name":"Евросеть","icon":"mobilephone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/Bell":{"tags":{"name":"Bell","shop":"mobile_phone"},"name":"Bell","icon":"mobilephone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/The Phone House":{"tags":{"name":"The Phone House","shop":"mobile_phone"},"name":"The Phone House","icon":"mobilephone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/SFR":{"tags":{"name":"SFR","shop":"mobile_phone"},"name":"SFR","icon":"mobilephone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/Связной":{"tags":{"name":"Связной","shop":"mobile_phone"},"name":"Связной","icon":"mobilephone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/Мегафон":{"tags":{"name":"Мегафон","shop":"mobile_phone"},"name":"Мегафон","icon":"mobilephone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/AT&T":{"tags":{"name":"AT&T","shop":"mobile_phone"},"name":"AT&T","icon":"mobilephone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/ドコモショップ (docomo shop)":{"tags":{"name":"ドコモショップ (docomo shop)","shop":"mobile_phone"},"name":"ドコモショップ (docomo shop)","icon":"mobilephone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/au":{"tags":{"name":"au","shop":"mobile_phone"},"name":"au","icon":"mobilephone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/Movistar":{"tags":{"name":"Movistar","shop":"mobile_phone"},"name":"Movistar","icon":"mobilephone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/mobile_phone/Bitė":{"tags":{"name":"Bitė","shop":"mobile_phone"},"name":"Bitė","icon":"mobilephone","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/computer/PC World":{"tags":{"name":"PC World","shop":"computer"},"name":"PC World","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/computer/DNS":{"tags":{"name":"DNS","shop":"computer"},"name":"DNS","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/hairdresser/Klier":{"tags":{"name":"Klier","shop":"hairdresser"},"name":"Klier","icon":"hairdresser","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/hairdresser/Supercuts":{"tags":{"name":"Supercuts","shop":"hairdresser"},"name":"Supercuts","icon":"hairdresser","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/hairdresser/Hairkiller":{"tags":{"name":"Hairkiller","shop":"hairdresser"},"name":"Hairkiller","icon":"hairdresser","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/hairdresser/Great Clips":{"tags":{"name":"Great Clips","shop":"hairdresser"},"name":"Great Clips","icon":"hairdresser","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/hairdresser/Парикмахерская":{"tags":{"name":"Парикмахерская","shop":"hairdresser"},"name":"Парикмахерская","icon":"hairdresser","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/hairdresser/Стиль":{"tags":{"name":"Стиль","shop":"hairdresser"},"name":"Стиль","icon":"hairdresser","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/hairdresser/Franck Provost":{"tags":{"name":"Franck Provost","shop":"hairdresser"},"name":"Franck Provost","icon":"hairdresser","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/hairdresser/Салон красоты":{"tags":{"name":"Салон красоты","shop":"hairdresser"},"name":"Салон красоты","icon":"hairdresser","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/hardware/1000 мелочей":{"tags":{"name":"1000 мелочей","shop":"hardware"},"name":"1000 мелочей","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/hardware/Хозтовары":{"tags":{"name":"Хозтовары","shop":"hardware"},"name":"Хозтовары","icon":"shop","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true},"shop/motorcycle/Yamaha":{"tags":{"name":"Yamaha","shop":"motorcycle"},"name":"Yamaha","icon":"scooter","geometry":["point","area"],"fields":["operator","address","building_area","opening_hours"],"suggestion":true}};
18954
18955 var defaults = {"area":["category-landuse","category-building","category-water-area","leisure/park","amenity/hospital","amenity/place_of_worship","amenity/cafe","amenity/restaurant","area"],"line":["category-road","category-rail","category-path","category-water-line","category-barrier","power/line","line"],"point":["leisure/park","amenity/hospital","amenity/place_of_worship","amenity/cafe","amenity/restaurant","amenity/fast_food","amenity/bar","amenity/bank","shop/supermarket","point"],"vertex":["highway/crosswalk","highway/crossing","railway/level_crossing","highway/traffic_signals","highway/turning_circle","traffic_calming","highway/mini_roundabout","highway/motorway_junction","vertex"],"relation":["category-route","category-restriction","type/boundary","type/multipolygon","type/site","relation"]};
18956
18957 var categories = {"category-barrier":{"geometry":"line","name":"Barrier Features","icon":"roadblock","members":["barrier/fence","barrier/wall","barrier/ditch","barrier/gate","barrier"]},"category-building":{"geometry":"area","name":"Building Features","icon":"building","members":["building","building/house","building/apartments","building/commercial","building/industrial","building/residential"]},"category-golf":{"geometry":"area","name":"Golf Features","icon":"golf","members":["golf/fairway","golf/green","golf/lateral_water_hazard_area","golf/rough","golf/bunker","golf/tee","golf/water_hazard_area"]},"category-landuse":{"geometry":"area","name":"Land Use Features","icon":"land-use","members":["landuse/residential","landuse/industrial","landuse/commercial","landuse/retail","landuse/farmland","landuse/farmyard","landuse/forest","landuse/meadow","landuse/cemetery","landuse/military"]},"category-path":{"geometry":"line","name":"Path Features","icon":"category-path","members":["highway/pedestrian","footway/crosswalk","footway/sidewalk","highway/steps","highway/path","highway/footway","highway/cycleway","highway/bridleway"]},"category-rail":{"geometry":"line","name":"Rail Features","icon":"category-rail","members":["railway/rail","railway/subway","railway/tram","railway/monorail","railway/disused","railway/abandoned"]},"category-restriction":{"geometry":"relation","name":"Restriction Features","icon":"restriction","members":["type/restriction/no_left_turn","type/restriction/no_right_turn","type/restriction/no_straight_on","type/restriction/no_u_turn","type/restriction/only_left_turn","type/restriction/only_right_turn","type/restriction/only_straight_on","type/restriction"]},"category-road":{"geometry":"line","name":"Road Features","icon":"category-roads","members":["highway/residential","highway/motorway","highway/trunk","highway/primary","highway/secondary","highway/tertiary","highway/unclassified","highway/service","highway/track","highway/motorway_link","highway/trunk_link","highway/primary_link","highway/secondary_link","highway/tertiary_link","highway/road"]},"category-route":{"geometry":"relation","name":"Route Features","icon":"route","members":["type/route/road","type/route/bicycle","type/route/foot","type/route/hiking","type/route/horse","type/route/bus","type/route/train","type/route/tram","type/route/ferry","type/route/power","type/route/pipeline","type/route/detour","type/route_master","type/route"]},"category-water-area":{"geometry":"area","name":"Water Features","icon":"water","members":["natural/water/lake","natural/water/pond","natural/water/reservoir","natural/water"]},"category-water-line":{"geometry":"line","name":"Water Features","icon":"category-water","members":["waterway/river","waterway/stream","waterway/canal","waterway/ditch","waterway/drain"]}};
18958
18959 var fields = {"access_simple":{"key":"access","type":"combo","label":"Allowed Access","options":["permissive","private","customers","no"]},"access_toilets":{"key":"access","type":"combo","label":"Access","options":["yes","permissive","private","customers"]},"access":{"keys":["access","foot","motor_vehicle","bicycle","horse"],"reference":{"key":"access"},"type":"access","label":"Allowed Access","placeholder":"Not Specified","strings":{"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"}}}},"address":{"type":"address","keys":["addr:city","addr:conscriptionnumber","addr:country","addr:district","addr:floor","addr:hamlet","addr:housename","addr:housenumber","addr:place","addr:postcode","addr:province","addr:state","addr:street","addr:subdistrict","addr:suburb"],"reference":{"key":"addr"},"icon":"address","universal":true,"label":"Address","strings":{"placeholders":{"city":"City","conscriptionnumber":"123","country":"Country","district":"District","floor":"Floor","hamlet":"Hamlet","housename":"Housename","housenumber":"123","place":"Place","postcode":"Postcode","province":"Province","state":"State","street":"Street","subdistrict":"Subdistrict","suburb":"Suburb"}}},"admin_level":{"key":"admin_level","type":"number","label":"Admin Level"},"aerialway":{"key":"aerialway","type":"typeCombo","label":"Type"},"aerialway/access":{"key":"aerialway:access","type":"combo","label":"Access","strings":{"options":{"entry":"Entry","exit":"Exit","both":"Both"}}},"aerialway/bubble":{"key":"aerialway:bubble","type":"check","label":"Bubble"},"aerialway/capacity":{"key":"aerialway:capacity","type":"number","label":"Capacity (per hour)","placeholder":"500, 2500, 5000..."},"aerialway/duration":{"key":"aerialway:duration","type":"number","label":"Duration (minutes)","placeholder":"1, 2, 3..."},"aerialway/heating":{"key":"aerialway:heating","type":"check","label":"Heated"},"aerialway/occupancy":{"key":"aerialway:occupancy","type":"number","label":"Occupancy","placeholder":"2, 4, 8..."},"aerialway/summer/access":{"key":"aerialway:summer:access","type":"combo","label":"Access (summer)","strings":{"options":{"entry":"Entry","exit":"Exit","both":"Both"}}},"aeroway":{"key":"aeroway","type":"typeCombo","label":"Type"},"amenity":{"key":"amenity","type":"typeCombo","label":"Type"},"area/highway":{"key":"area:highway","type":"typeCombo","label":"Type"},"artist":{"key":"artist_name","type":"text","label":"Artist"},"artwork_type":{"key":"artwork_type","type":"combo","label":"Type"},"atm":{"key":"atm","type":"check","label":"ATM"},"backrest":{"key":"backrest","type":"check","label":"Backrest"},"barrier":{"key":"barrier","type":"typeCombo","label":"Type"},"beauty":{"key":"beauty","type":"combo","label":"Shop Type"},"bench":{"key":"bench","type":"check","label":"Bench"},"bicycle_parking":{"key":"bicycle_parking","type":"combo","label":"Type"},"bin":{"key":"bin","type":"check","label":"Waste Bin"},"blood_components":{"key":"blood:","type":"multiCombo","label":"Blood Components","strings":{"options":{"whole":"whole blood","plasma":"plasma","platelets":"platelets","stemcells":"stem cell samples"}}},"board_type":{"key":"board_type","type":"typeCombo","label":"Type"},"boundary":{"key":"boundary","type":"combo","label":"Type"},"brand":{"key":"brand","type":"text","label":"Brand"},"building_area":{"key":"building","type":"combo","default":"yes","geometry":"area","label":"Building"},"building":{"key":"building","type":"combo","label":"Building"},"capacity":{"key":"capacity","type":"number","label":"Capacity","placeholder":"50, 100, 200..."},"cardinal_direction":{"key":"direction","type":"combo","label":"Direction","strings":{"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":{"key":"direction","type":"combo","label":"Direction","strings":{"options":{"clockwise":"Clockwise","anticlockwise":"Counterclockwise"}}},"collection_times":{"key":"collection_times","type":"text","label":"Collection Times"},"construction":{"key":"construction","type":"combo","label":"Type"},"content":{"key":"content","type":"combo","label":"Contents"},"country":{"key":"country","type":"combo","label":"Country"},"covered":{"key":"covered","type":"check","label":"Covered"},"craft":{"key":"craft","type":"typeCombo","label":"Type"},"crop":{"key":"crop","type":"combo","label":"Crop"},"crossing":{"key":"crossing","type":"combo","label":"Type"},"cuisine":{"key":"cuisine","type":"combo","label":"Cuisine"},"currency_multi":{"key":"currency:","type":"multiCombo","label":"Currency Types"},"cycle_network":{"key":"cycle_network","type":"networkCombo","label":"Network"},"cycleway":{"keys":["cycleway:left","cycleway:right"],"reference":{"key":"cycleway"},"type":"cycleway","label":"Bike Lanes","placeholder":"none","strings":{"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"}}}},"date":{"key":"date","type":"check","label":"Date"},"delivery":{"key":"delivery","type":"check","label":"Delivery"},"denomination":{"key":"denomination","type":"combo","label":"Denomination"},"denotation":{"key":"denotation","type":"combo","label":"Denotation"},"description":{"key":"description","type":"textarea","label":"Description","universal":true},"diaper":{"key":"diaper","type":"combo","label":"Diaper Changing Available","options":["yes","no","room","1","2","3","4","5"]},"display":{"key":"display","type":"combo","label":"Display","options":["analog","digital","sundial","unorthodox"]},"dock":{"key":"dock","type":"combo","label":"Type"},"drive_through":{"key":"drive_through","type":"check","label":"Drive-Through"},"electrified":{"key":"electrified","type":"combo","label":"Electrification","placeholder":"Contact Line, Electrified Rail...","strings":{"options":{"contact_line":"Contact Line","rail":"Electrified Rail","yes":"Yes (unspecified)","no":"No"}}},"elevation":{"key":"ele","type":"number","icon":"elevation","universal":true,"label":"Elevation"},"emergency":{"key":"emergency","type":"check","label":"Emergency"},"entrance":{"key":"entrance","type":"typeCombo","label":"Type"},"except":{"key":"except","type":"combo","label":"Exceptions"},"fax":{"key":"fax","type":"tel","label":"Fax","placeholder":"+31 42 123 4567"},"fee":{"key":"fee","type":"check","label":"Fee"},"fire_hydrant/type":{"key":"fire_hydrant:type","type":"combo","label":"Type","strings":{"options":{"pillar":"Pillar/Aboveground","underground":"Underground","wall":"Wall","pond":"Pond"}}},"fixme":{"key":"fixme","type":"textarea","label":"Fix Me","universal":true},"fuel_multi":{"key":"fuel:","type":"multiCombo","label":"Fuel Types"},"fuel":{"key":"fuel","type":"combo","label":"Fuel"},"gauge":{"key":"gauge","type":"combo","label":"Gauge"},"gender":{"type":"radio","keys":["male","female","unisex"],"label":"Gender","placeholder":"Unknown","strings":{"options":{"male":"Male","female":"Female","unisex":"Unisex"}}},"generator/method":{"key":"generator:method","type":"combo","label":"Method"},"generator/source":{"key":"generator:source","type":"combo","label":"Source"},"generator/type":{"key":"generator:type","type":"combo","label":"Type"},"golf_hole":{"key":"ref","type":"text","label":"Reference","placeholder":"Hole number (1-18)"},"handicap":{"key":"handicap","type":"number","label":"Handicap","placeholder":"1-18"},"handrail":{"key":"handrail","type":"check","label":"Handrail"},"height":{"key":"height","type":"number","label":"Height (meters)"},"highway":{"key":"highway","type":"typeCombo","label":"Type"},"historic":{"key":"historic","type":"typeCombo","label":"Type"},"hoops":{"key":"hoops","type":"number","label":"Hoops","placeholder":"1, 2, 4..."},"iata":{"key":"iata","type":"text","label":"IATA"},"icao":{"key":"icao","type":"text","label":"ICAO"},"incline_steps":{"key":"incline","type":"combo","label":"Incline","strings":{"options":{"up":"Up","down":"Down"}}},"incline":{"key":"incline","type":"combo","label":"Incline"},"indoor":{"key":"indoor","type":"check","label":"Indoor"},"information":{"key":"information","type":"typeCombo","label":"Type"},"internet_access":{"key":"internet_access","type":"combo","label":"Internet Access","strings":{"options":{"yes":"Yes","no":"No","wlan":"Wifi","wired":"Wired","terminal":"Terminal"}}},"internet_access/fee":{"key":"internet_access:fee","type":"check","label":"Internet Access Fee"},"kerb":{"key":"kerb","type":"combo","label":"Curb Ramp"},"lamp_type":{"key":"lamp_type","type":"combo","label":"Type"},"landuse":{"key":"landuse","type":"typeCombo","label":"Type"},"lanes":{"key":"lanes","type":"number","label":"Lanes","placeholder":"1, 2, 3..."},"layer":{"key":"layer","type":"combo","label":"Layer"},"leaf_cycle_singular":{"key":"leaf_cycle","type":"combo","label":"Leaf Cycle","strings":{"options":{"evergreen":"Evergreen","deciduous":"Deciduous","semi_evergreen":"Semi-Evergreen","semi_deciduous":"Semi-Deciduous"}}},"leaf_cycle":{"key":"leaf_cycle","type":"combo","label":"Leaf Cycle","strings":{"options":{"evergreen":"Evergreen","deciduous":"Deciduous","semi_evergreen":"Semi-Evergreen","semi_deciduous":"Semi-Deciduous","mixed":"Mixed"}}},"leaf_type_singular":{"key":"leaf_type","type":"combo","label":"Leaf Type","strings":{"options":{"broadleaved":"Broadleaved","needleleaved":"Needleleaved","leafless":"Leafless"}}},"leaf_type":{"key":"leaf_type","type":"combo","label":"Leaf Type","strings":{"options":{"broadleaved":"Broadleaved","needleleaved":"Needleleaved","mixed":"Mixed","leafless":"Leafless"}}},"leisure":{"key":"leisure","type":"typeCombo","label":"Type"},"length":{"key":"length","type":"number","label":"Length (Meters)"},"level":{"key":"level","type":"combo","label":"Level","universal":true},"levels":{"key":"building:levels","type":"number","label":"Levels","placeholder":"2, 4, 6..."},"lit":{"key":"lit","type":"check","label":"Lit"},"location":{"key":"location","type":"combo","label":"Location"},"man_made":{"key":"man_made","type":"typeCombo","label":"Type"},"map_size":{"key":"map_size","type":"typeCombo","label":"Coverage"},"map_type":{"key":"map_type","type":"typeCombo","label":"Type"},"maxspeed":{"key":"maxspeed","type":"maxspeed","label":"Speed Limit","placeholder":"40, 50, 60..."},"maxstay":{"key":"maxstay","type":"combo","label":"Max Stay","options":["15 min","30 min","45 min","1 hr","1.5 hr","2 hr","2.5 hr","3 hr","4 hr","1 day","2 day"],"snake_case":false},"mtb/scale":{"key":"mtb:scale","type":"combo","label":"Mountain Biking Difficulty","placeholder":"0, 1, 2, 3...","strings":{"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":{"key":"mtb:scale:imba","type":"combo","label":"IMBA Trail Difficulty","placeholder":"Easy, Medium, Difficult...","strings":{"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":{"key":"mtb:scale:uphill","type":"combo","label":"Mountain Biking Uphill Difficulty","placeholder":"0, 1, 2, 3...","strings":{"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":{"key":"name","type":"localized","label":"Name","placeholder":"Common name (if any)"},"natural":{"key":"natural","type":"typeCombo","label":"Natural"},"network_bicycle":{"key":"network","type":"combo","label":"Network Type","placeholder":"Local, Regional, National, International","strings":{"options":{"lcn":"Local","rcn":"Regional","ncn":"National","icn":"International"}}},"network_foot":{"key":"network","type":"combo","label":"Network Type","placeholder":"Local, Regional, National, International","strings":{"options":{"lwn":"Local","rwn":"Regional","nwn":"National","iwn":"International"}}},"network_horse":{"key":"network","type":"combo","label":"Network Type","placeholder":"Local, Regional, National, International","strings":{"options":{"lhn":"Local","rhn":"Regional","nhn":"National","ihn":"International"}}},"network_road":{"key":"network","type":"networkCombo","label":"Network"},"network":{"key":"network","type":"text","label":"Network"},"note":{"key":"note","type":"textarea","universal":true,"icon":"note","label":"Note"},"office":{"key":"office","type":"typeCombo","label":"Type"},"oneway_yes":{"key":"oneway","type":"check","label":"One Way","strings":{"options":{"undefined":"Assumed to be Yes","yes":"Yes","no":"No"}}},"oneway":{"key":"oneway","type":"check","label":"One Way","strings":{"options":{"undefined":"Assumed to be No","yes":"Yes","no":"No"}}},"opening_hours":{"key":"opening_hours","type":"text","label":"Hours"},"operator":{"key":"operator","type":"text","label":"Operator"},"par":{"key":"par","type":"number","label":"Par","placeholder":"3, 4, 5..."},"parallel_direction":{"key":"direction","type":"combo","label":"Direction","strings":{"options":{"forward":"Forward","backward":"Backward"}}},"park_ride":{"key":"park_ride","type":"check","label":"Park and Ride"},"parking":{"key":"parking","type":"combo","label":"Type","strings":{"options":{"surface":"Surface","multi-storey":"Multilevel","underground":"Underground","sheds":"Sheds","carports":"Carports","garage_boxes":"Garage Boxes","lane":"Roadside Lane"}}},"payment_multi":{"key":"payment:","type":"multiCombo","label":"Payment Types"},"phone":{"key":"phone","type":"tel","icon":"telephone","universal":true,"label":"Phone","placeholder":"+31 42 123 4567"},"piste/difficulty":{"key":"piste:difficulty","type":"combo","label":"Difficulty","placeholder":"Easy, Intermediate, Advanced...","strings":{"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":{"key":"piste:grooming","type":"combo","label":"Grooming","strings":{"options":{"classic":"Classic","mogul":"Mogul","backcountry":"Backcountry","classic+skating":"Classic and Skating","scooter":"Scooter/Snowmobile","skating":"Skating"}}},"piste/type":{"key":"piste:type","type":"typeCombo","label":"Type","strings":{"options":{"downhill":"Downhill","nordic":"Nordic","skitour":"Skitour","sled":"Sled","hike":"Hike","sleigh":"Sleigh","ice_skate":"Ice Skate","snow_park":"Snow Park","playground":"Playground"}}},"place":{"key":"place","type":"typeCombo","label":"Type"},"population":{"key":"population","type":"text","label":"Population"},"power_supply":{"key":"power_supply","type":"check","label":"Power Supply"},"power":{"key":"power","type":"typeCombo","label":"Type"},"railway":{"key":"railway","type":"typeCombo","label":"Type"},"recycling_accepts":{"key":"recycling:","type":"multiCombo","label":"Accepts"},"recycling_type":{"key":"recycling_type","default":"container","type":"combo","label":"Recycling Type","strings":{"options":{"container":"Container","centre":"Recycling Center"}}},"ref":{"key":"ref","type":"text","label":"Reference"},"relation":{"key":"type","type":"combo","label":"Type"},"religion":{"key":"religion","type":"combo","label":"Religion"},"restriction":{"key":"restriction","type":"combo","label":"Type"},"restrictions":{"type":"restrictions","geometry":"vertex","icon":"restrictions","reference":{"rtype":"restriction"},"label":"Turn Restrictions"},"rooms":{"key":"rooms","type":"number","label":"Rooms"},"route_master":{"key":"route_master","type":"combo","label":"Type"},"route":{"key":"route","type":"combo","label":"Type"},"sac_scale":{"key":"sac_scale","type":"combo","label":"Hiking Difficulty","placeholder":"Mountain Hiking, Alpine Hiking...","strings":{"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":{"key":"sanitary_dump_station","type":"check","label":"Toilet Disposal"},"seasonal":{"key":"seasonal","type":"check","label":"Seasonal"},"second_hand":{"key":"second_hand","type":"combo","label":"Sells Used","placeholder":"Yes, No, Only","strings":{"options":{"yes":"Yes","no":"No","only":"Only"}}},"service_rail":{"key":"service","type":"combo","label":"Service Type","strings":{"options":{"spur":"Spur","yard":"Yard","siding":"Siding","crossover":"Crossover"}}},"service":{"key":"service","type":"combo","label":"Type","options":["parking_aisle","driveway","alley","emergency_access","drive-through"]},"service/bicycle":{"key":"service:bicycle:","type":"multiCombo","label":"Services"},"shelter_type":{"key":"shelter_type","type":"combo","label":"Type"},"shelter":{"key":"shelter","type":"check","label":"Shelter"},"shop":{"key":"shop","type":"typeCombo","label":"Type"},"site":{"key":"site","type":"combo","label":"Type"},"smoking":{"key":"smoking","type":"combo","label":"Smoking","placeholder":"No, Separated, Yes...","strings":{"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":{"key":"smoothness","type":"combo","label":"Smoothness","placeholder":"Thin Rollers, Wheels, Off-Road...","strings":{"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":{"key":"social_facility:for","type":"radio","label":"People served","placeholder":"Homeless, Disabled, Child, etc","options":["abused","child","disabled","diseased","drug_addicted","homeless","juvenile","mental_health","migrant","orphan","senior","underprivileged","unemployed","victim"]},"source":{"key":"source","type":"text","icon":"source","universal":true,"label":"Source"},"sport_ice":{"key":"sport","type":"combo","label":"Sport","options":["skating","hockey","multi","curling","ice_stock"]},"sport_racing":{"key":"sport","type":"combo","label":"Sport","options":["cycling","dog_racing","horse_racing","karting","motor","motocross","running"]},"sport":{"key":"sport","type":"combo","label":"Sport"},"stars":{"key":"stars","type":"number","label":"Stars"},"stop":{"key":"stop","type":"combo","label":"Stop Type","strings":{"options":{"all":"All Ways","minor":"Minor Road"}}},"structure":{"type":"radio","keys":["bridge","tunnel","embankment","cutting","ford"],"label":"Structure","placeholder":"Unknown","strings":{"options":{"bridge":"Bridge","tunnel":"Tunnel","embankment":"Embankment","cutting":"Cutting","ford":"Ford"}}},"studio":{"key":"studio","type":"combo","label":"Type"},"substation":{"key":"substation","type":"typeCombo","label":"Type"},"supervised":{"key":"supervised","type":"check","label":"Supervised"},"support":{"key":"support","type":"combo","label":"Support"},"surface":{"key":"surface","type":"combo","label":"Surface"},"tactile_paving":{"key":"tactile_paving","type":"check","label":"Tactile Paving"},"takeaway":{"key":"takeaway","type":"combo","label":"Takeaway","placeholder":"Yes, No, Takeaway Only...","strings":{"options":{"yes":"Yes","no":"No","only":"Takeaway Only"}}},"toilets/disposal":{"key":"toilets:disposal","type":"combo","label":"Disposal","strings":{"options":{"flush":"Flush","pitlatrine":"Pit/Latrine","chemical":"Chemical","bucket":"Bucket"}}},"tourism":{"key":"tourism","type":"typeCombo","label":"Type"},"tower/construction":{"key":"tower:construction","type":"combo","label":"Construction","placeholder":"Guyed, Lattice, Concealed, ..."},"tower/type":{"key":"tower:type","type":"combo","label":"Type"},"tracktype":{"key":"tracktype","type":"combo","label":"Track Type","placeholder":"Solid, Mostly Solid, Soft...","strings":{"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_calming":{"key":"traffic_calming","type":"typeCombo","label":"Type"},"traffic_signals":{"key":"traffic_signals","type":"combo","label":"Type","default":"signal"},"trail_visibility":{"key":"trail_visibility","type":"combo","label":"Trail Visibility","placeholder":"Excellent, Good, Bad...","strings":{"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":{"key":"trees","type":"combo","label":"Trees"},"tunnel":{"key":"tunnel","type":"combo","label":"Tunnel"},"vending":{"key":"vending","type":"combo","label":"Type of Goods"},"visibility":{"key":"visibility","type":"combo","label":"Visibility","strings":{"options":{"house":"Up to 5m (16ft)","street":"5 to 20m (16 to 65ft)","area":"Over 20m (65ft)"}}},"water_point":{"key":"water_point","type":"check","label":"Water Point"},"water":{"key":"water","type":"combo","label":"Type"},"waterway":{"key":"waterway","type":"typeCombo","label":"Type"},"website":{"key":"website","type":"url","icon":"website","placeholder":"http://example.com/","universal":true,"label":"Website"},"wetland":{"key":"wetland","type":"combo","label":"Type"},"wheelchair":{"key":"wheelchair","type":"radio","options":["yes","limited","no"],"icon":"wheelchair","universal":true,"label":"Wheelchair Access"},"width":{"key":"width","type":"number","label":"Width (Meters)"},"wikipedia":{"key":"wikipedia","keys":["wikipedia","wikidata"],"type":"wikipedia","icon":"wikipedia","universal":true,"label":"Wikipedia"}};
18960
18961 var data = {
18962     imagery: dataImagery,
18963     presets: {
18964         presets: presets,
18965         defaults: defaults,
18966         categories: categories,
18967         fields: fields
18968     }
18969 };
18970
18971 function osmEntity$$1(attrs) {
18972     // For prototypal inheritance.
18973     if (this instanceof osmEntity$$1) return;
18974
18975     // Create the appropriate subtype.
18976     if (attrs && attrs.type) {
18977         return osmEntity$$1[attrs.type].apply(this, arguments);
18978     } else if (attrs && attrs.id) {
18979         return osmEntity$$1[osmEntity$$1.id.type(attrs.id)].apply(this, arguments);
18980     }
18981
18982     // Initialize a generic Entity (used only in tests).
18983     return (new osmEntity$$1()).initialize(arguments);
18984 }
18985
18986
18987 osmEntity$$1.id = function(type) {
18988     return osmEntity$$1.id.fromOSM(type, osmEntity$$1.id.next[type]--);
18989 };
18990
18991
18992 osmEntity$$1.id.next = {
18993     node: -1, way: -1, relation: -1
18994 };
18995
18996
18997 osmEntity$$1.id.fromOSM = function(type, id) {
18998     return type[0] + id;
18999 };
19000
19001
19002 osmEntity$$1.id.toOSM = function(id) {
19003     return id.slice(1);
19004 };
19005
19006
19007 osmEntity$$1.id.type = function(id) {
19008     return { 'n': 'node', 'w': 'way', 'r': 'relation' }[id[0]];
19009 };
19010
19011
19012 // A function suitable for use as the second argument to d3.selection#data().
19013 osmEntity$$1.key = function(entity) {
19014     return entity.id + 'v' + (entity.v || 0);
19015 };
19016
19017
19018 osmEntity$$1.prototype = {
19019
19020     tags: {},
19021
19022
19023     initialize: function(sources) {
19024         for (var i = 0; i < sources.length; ++i) {
19025             var source = sources[i];
19026             for (var prop in source) {
19027                 if (Object.prototype.hasOwnProperty.call(source, prop)) {
19028                     if (source[prop] === undefined) {
19029                         delete this[prop];
19030                     } else {
19031                         this[prop] = source[prop];
19032                     }
19033                 }
19034             }
19035         }
19036
19037         if (!this.id && this.type) {
19038             this.id = osmEntity$$1.id(this.type);
19039         }
19040         if (!this.hasOwnProperty('visible')) {
19041             this.visible = true;
19042         }
19043
19044         if (debug) {
19045             Object.freeze(this);
19046             Object.freeze(this.tags);
19047
19048             if (this.loc) Object.freeze(this.loc);
19049             if (this.nodes) Object.freeze(this.nodes);
19050             if (this.members) Object.freeze(this.members);
19051         }
19052
19053         return this;
19054     },
19055
19056
19057     copy: function(resolver, copies) {
19058         if (copies[this.id])
19059             return copies[this.id];
19060
19061         var copy = osmEntity$$1(this, {id: undefined, user: undefined, version: undefined});
19062         copies[this.id] = copy;
19063
19064         return copy;
19065     },
19066
19067
19068     osmId: function() {
19069         return osmEntity$$1.id.toOSM(this.id);
19070     },
19071
19072
19073     isNew: function() {
19074         return this.osmId() < 0;
19075     },
19076
19077
19078     update: function(attrs) {
19079         return osmEntity$$1(this, attrs, {v: 1 + (this.v || 0)});
19080     },
19081
19082
19083     mergeTags: function(tags) {
19084         var merged = lodash.clone(this.tags), changed = false;
19085         for (var k in tags) {
19086             var t1 = merged[k],
19087                 t2 = tags[k];
19088             if (!t1) {
19089                 changed = true;
19090                 merged[k] = t2;
19091             } else if (t1 !== t2) {
19092                 changed = true;
19093                 merged[k] = lodash.union(t1.split(/;\s*/), t2.split(/;\s*/)).join(';');
19094             }
19095         }
19096         return changed ? this.update({tags: merged}) : this;
19097     },
19098
19099
19100     intersects: function(extent, resolver) {
19101         return this.extent(resolver).intersects(extent);
19102     },
19103
19104
19105     isUsed: function(resolver) {
19106         return lodash.without(Object.keys(this.tags), 'area').length > 0 ||
19107             resolver.parentRelations(this).length > 0;
19108     },
19109
19110
19111     hasInterestingTags: function() {
19112         return lodash.keys(this.tags).some(osmIsInterestingTag);
19113     },
19114
19115
19116     isHighwayIntersection: function() {
19117         return false;
19118     },
19119
19120
19121     deprecatedTags: function() {
19122         var tags = lodash.toPairs(this.tags);
19123         var deprecated = {};
19124
19125         dataDeprecated.forEach(function(d) {
19126             var match = lodash.toPairs(d.old)[0];
19127             tags.forEach(function(t) {
19128                 if (t[0] === match[0] &&
19129                     (t[1] === match[1] || match[1] === '*')) {
19130                     deprecated[t[0]] = t[1];
19131                 }
19132             });
19133         });
19134
19135         return deprecated;
19136     }
19137 };
19138
19139 function geoExtent$$1(min, max) {
19140     if (!(this instanceof geoExtent$$1)) return new geoExtent$$1(min, max);
19141     if (min instanceof geoExtent$$1) {
19142         return min;
19143     } else if (min && min.length === 2 && min[0].length === 2 && min[1].length === 2) {
19144         this[0] = min[0];
19145         this[1] = min[1];
19146     } else {
19147         this[0] = min        || [ Infinity,  Infinity];
19148         this[1] = max || min || [-Infinity, -Infinity];
19149     }
19150 }
19151
19152 geoExtent$$1.prototype = new Array(2);
19153
19154 lodash.extend(geoExtent$$1.prototype, {
19155
19156     equals: function (obj) {
19157         return this[0][0] === obj[0][0] &&
19158             this[0][1] === obj[0][1] &&
19159             this[1][0] === obj[1][0] &&
19160             this[1][1] === obj[1][1];
19161     },
19162
19163
19164     extend: function(obj) {
19165         if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19166         return geoExtent$$1(
19167             [Math.min(obj[0][0], this[0][0]), Math.min(obj[0][1], this[0][1])],
19168             [Math.max(obj[1][0], this[1][0]), Math.max(obj[1][1], this[1][1])]
19169         );
19170     },
19171
19172
19173     _extend: function(extent) {
19174         this[0][0] = Math.min(extent[0][0], this[0][0]);
19175         this[0][1] = Math.min(extent[0][1], this[0][1]);
19176         this[1][0] = Math.max(extent[1][0], this[1][0]);
19177         this[1][1] = Math.max(extent[1][1], this[1][1]);
19178     },
19179
19180
19181     area: function() {
19182         return Math.abs((this[1][0] - this[0][0]) * (this[1][1] - this[0][1]));
19183     },
19184
19185
19186     center: function() {
19187         return [(this[0][0] + this[1][0]) / 2,
19188                 (this[0][1] + this[1][1]) / 2];
19189     },
19190
19191
19192     rectangle: function() {
19193         return [this[0][0], this[0][1], this[1][0], this[1][1]];
19194     },
19195
19196
19197     bbox: function() {
19198         return { minX: this[0][0], minY: this[0][1], maxX: this[1][0], maxY: this[1][1] };
19199     },
19200
19201
19202     polygon: function() {
19203         return [
19204             [this[0][0], this[0][1]],
19205             [this[0][0], this[1][1]],
19206             [this[1][0], this[1][1]],
19207             [this[1][0], this[0][1]],
19208             [this[0][0], this[0][1]]
19209         ];
19210     },
19211
19212
19213     contains: function(obj) {
19214         if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19215         return obj[0][0] >= this[0][0] &&
19216                obj[0][1] >= this[0][1] &&
19217                obj[1][0] <= this[1][0] &&
19218                obj[1][1] <= this[1][1];
19219     },
19220
19221
19222     intersects: function(obj) {
19223         if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19224         return obj[0][0] <= this[1][0] &&
19225                obj[0][1] <= this[1][1] &&
19226                obj[1][0] >= this[0][0] &&
19227                obj[1][1] >= this[0][1];
19228     },
19229
19230
19231     intersection: function(obj) {
19232         if (!this.intersects(obj)) return new geoExtent$$1();
19233         return new geoExtent$$1(
19234             [Math.max(obj[0][0], this[0][0]), Math.max(obj[0][1], this[0][1])],
19235             [Math.min(obj[1][0], this[1][0]), Math.min(obj[1][1], this[1][1])]
19236         );
19237     },
19238
19239
19240     percentContainedIn: function(obj) {
19241         if (!(obj instanceof geoExtent$$1)) obj = new geoExtent$$1(obj);
19242         var a1 = this.intersection(obj).area(),
19243             a2 = this.area();
19244
19245         if (a1 === Infinity || a2 === Infinity || a1 === 0 || a2 === 0) {
19246             return 0;
19247         } else {
19248             return a1 / a2;
19249         }
19250     },
19251
19252
19253     padByMeters: function(meters) {
19254         var dLat = geoMetersToLat(meters),
19255             dLon = geoMetersToLon(meters, this.center()[1]);
19256         return geoExtent$$1(
19257             [this[0][0] - dLon, this[0][1] - dLat],
19258             [this[1][0] + dLon, this[1][1] + dLat]
19259         );
19260     },
19261
19262
19263     toParam: function() {
19264         return this.rectangle().join(',');
19265     }
19266
19267 });
19268
19269 var version = "4.3.0";
19270
19271 var ascending = function(a, b) {
19272   return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
19273 };
19274
19275 var bisector = function(compare) {
19276   if (compare.length === 1) compare = ascendingComparator(compare);
19277   return {
19278     left: function(a, x, lo, hi) {
19279       if (lo == null) lo = 0;
19280       if (hi == null) hi = a.length;
19281       while (lo < hi) {
19282         var mid = lo + hi >>> 1;
19283         if (compare(a[mid], x) < 0) lo = mid + 1;
19284         else hi = mid;
19285       }
19286       return lo;
19287     },
19288     right: function(a, x, lo, hi) {
19289       if (lo == null) lo = 0;
19290       if (hi == null) hi = a.length;
19291       while (lo < hi) {
19292         var mid = lo + hi >>> 1;
19293         if (compare(a[mid], x) > 0) hi = mid;
19294         else lo = mid + 1;
19295       }
19296       return lo;
19297     }
19298   };
19299 };
19300
19301 function ascendingComparator(f) {
19302   return function(d, x) {
19303     return ascending(f(d), x);
19304   };
19305 }
19306
19307 var ascendingBisect = bisector(ascending);
19308 var bisectRight = ascendingBisect.right;
19309 var bisectLeft = ascendingBisect.left;
19310
19311 var descending = function(a, b) {
19312   return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
19313 };
19314
19315 var number = function(x) {
19316   return x === null ? NaN : +x;
19317 };
19318
19319 var variance = function(array, f) {
19320   var n = array.length,
19321       m = 0,
19322       a,
19323       d,
19324       s = 0,
19325       i = -1,
19326       j = 0;
19327
19328   if (f == null) {
19329     while (++i < n) {
19330       if (!isNaN(a = number(array[i]))) {
19331         d = a - m;
19332         m += d / ++j;
19333         s += d * (a - m);
19334       }
19335     }
19336   }
19337
19338   else {
19339     while (++i < n) {
19340       if (!isNaN(a = number(f(array[i], i, array)))) {
19341         d = a - m;
19342         m += d / ++j;
19343         s += d * (a - m);
19344       }
19345     }
19346   }
19347
19348   if (j > 1) return s / (j - 1);
19349 };
19350
19351 var deviation = function(array, f) {
19352   var v = variance(array, f);
19353   return v ? Math.sqrt(v) : v;
19354 };
19355
19356 var extent = function(array, f) {
19357   var i = -1,
19358       n = array.length,
19359       a,
19360       b,
19361       c;
19362
19363   if (f == null) {
19364     while (++i < n) if ((b = array[i]) != null && b >= b) { a = c = b; break; }
19365     while (++i < n) if ((b = array[i]) != null) {
19366       if (a > b) a = b;
19367       if (c < b) c = b;
19368     }
19369   }
19370
19371   else {
19372     while (++i < n) if ((b = f(array[i], i, array)) != null && b >= b) { a = c = b; break; }
19373     while (++i < n) if ((b = f(array[i], i, array)) != null) {
19374       if (a > b) a = b;
19375       if (c < b) c = b;
19376     }
19377   }
19378
19379   return [a, c];
19380 };
19381
19382 var array = Array.prototype;
19383
19384 var slice = array.slice;
19385 var map = array.map;
19386
19387 var constant$1 = function(x) {
19388   return function() {
19389     return x;
19390   };
19391 };
19392
19393 var identity = function(x) {
19394   return x;
19395 };
19396
19397 var range = function(start, stop, step) {
19398   start = +start, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start, start = 0, 1) : n < 3 ? 1 : +step;
19399
19400   var i = -1,
19401       n = Math.max(0, Math.ceil((stop - start) / step)) | 0,
19402       range = new Array(n);
19403
19404   while (++i < n) {
19405     range[i] = start + i * step;
19406   }
19407
19408   return range;
19409 };
19410
19411 var e10 = Math.sqrt(50);
19412 var e5 = Math.sqrt(10);
19413 var e2 = Math.sqrt(2);
19414
19415 var ticks = function(start, stop, count) {
19416   var step = tickStep(start, stop, count);
19417   return range(
19418     Math.ceil(start / step) * step,
19419     Math.floor(stop / step) * step + step / 2, // inclusive
19420     step
19421   );
19422 };
19423
19424 function tickStep(start, stop, count) {
19425   var step0 = Math.abs(stop - start) / Math.max(0, count),
19426       step1 = Math.pow(10, Math.floor(Math.log(step0) / Math.LN10)),
19427       error = step0 / step1;
19428   if (error >= e10) step1 *= 10;
19429   else if (error >= e5) step1 *= 5;
19430   else if (error >= e2) step1 *= 2;
19431   return stop < start ? -step1 : step1;
19432 }
19433
19434 var sturges = function(values) {
19435   return Math.ceil(Math.log(values.length) / Math.LN2) + 1;
19436 };
19437
19438 var histogram = function() {
19439   var value = identity,
19440       domain = extent,
19441       threshold = sturges;
19442
19443   function histogram(data) {
19444     var i,
19445         n = data.length,
19446         x,
19447         values = new Array(n);
19448
19449     for (i = 0; i < n; ++i) {
19450       values[i] = value(data[i], i, data);
19451     }
19452
19453     var xz = domain(values),
19454         x0 = xz[0],
19455         x1 = xz[1],
19456         tz = threshold(values, x0, x1);
19457
19458     // Convert number of thresholds into uniform thresholds.
19459     if (!Array.isArray(tz)) tz = ticks(x0, x1, tz);
19460
19461     // Remove any thresholds outside the domain.
19462     var m = tz.length;
19463     while (tz[0] <= x0) tz.shift(), --m;
19464     while (tz[m - 1] >= x1) tz.pop(), --m;
19465
19466     var bins = new Array(m + 1),
19467         bin;
19468
19469     // Initialize bins.
19470     for (i = 0; i <= m; ++i) {
19471       bin = bins[i] = [];
19472       bin.x0 = i > 0 ? tz[i - 1] : x0;
19473       bin.x1 = i < m ? tz[i] : x1;
19474     }
19475
19476     // Assign data to bins by value, ignoring any outside the domain.
19477     for (i = 0; i < n; ++i) {
19478       x = values[i];
19479       if (x0 <= x && x <= x1) {
19480         bins[bisectRight(tz, x, 0, m)].push(data[i]);
19481       }
19482     }
19483
19484     return bins;
19485   }
19486
19487   histogram.value = function(_) {
19488     return arguments.length ? (value = typeof _ === "function" ? _ : constant$1(_), histogram) : value;
19489   };
19490
19491   histogram.domain = function(_) {
19492     return arguments.length ? (domain = typeof _ === "function" ? _ : constant$1([_[0], _[1]]), histogram) : domain;
19493   };
19494
19495   histogram.thresholds = function(_) {
19496     return arguments.length ? (threshold = typeof _ === "function" ? _ : Array.isArray(_) ? constant$1(slice.call(_)) : constant$1(_), histogram) : threshold;
19497   };
19498
19499   return histogram;
19500 };
19501
19502 var threshold = function(array, p, f) {
19503   if (f == null) f = number;
19504   if (!(n = array.length)) return;
19505   if ((p = +p) <= 0 || n < 2) return +f(array[0], 0, array);
19506   if (p >= 1) return +f(array[n - 1], n - 1, array);
19507   var n,
19508       h = (n - 1) * p,
19509       i = Math.floor(h),
19510       a = +f(array[i], i, array),
19511       b = +f(array[i + 1], i + 1, array);
19512   return a + (b - a) * (h - i);
19513 };
19514
19515 var freedmanDiaconis = function(values, min, max) {
19516   values = map.call(values, number).sort(ascending);
19517   return Math.ceil((max - min) / (2 * (threshold(values, 0.75) - threshold(values, 0.25)) * Math.pow(values.length, -1 / 3)));
19518 };
19519
19520 var scott = function(values, min, max) {
19521   return Math.ceil((max - min) / (3.5 * deviation(values) * Math.pow(values.length, -1 / 3)));
19522 };
19523
19524 var max = function(array, f) {
19525   var i = -1,
19526       n = array.length,
19527       a,
19528       b;
19529
19530   if (f == null) {
19531     while (++i < n) if ((b = array[i]) != null && b >= b) { a = b; break; }
19532     while (++i < n) if ((b = array[i]) != null && b > a) a = b;
19533   }
19534
19535   else {
19536     while (++i < n) if ((b = f(array[i], i, array)) != null && b >= b) { a = b; break; }
19537     while (++i < n) if ((b = f(array[i], i, array)) != null && b > a) a = b;
19538   }
19539
19540   return a;
19541 };
19542
19543 var mean = function(array, f) {
19544   var s = 0,
19545       n = array.length,
19546       a,
19547       i = -1,
19548       j = n;
19549
19550   if (f == null) {
19551     while (++i < n) if (!isNaN(a = number(array[i]))) s += a; else --j;
19552   }
19553
19554   else {
19555     while (++i < n) if (!isNaN(a = number(f(array[i], i, array)))) s += a; else --j;
19556   }
19557
19558   if (j) return s / j;
19559 };
19560
19561 var median = function(array, f) {
19562   var numbers = [],
19563       n = array.length,
19564       a,
19565       i = -1;
19566
19567   if (f == null) {
19568     while (++i < n) if (!isNaN(a = number(array[i]))) numbers.push(a);
19569   }
19570
19571   else {
19572     while (++i < n) if (!isNaN(a = number(f(array[i], i, array)))) numbers.push(a);
19573   }
19574
19575   return threshold(numbers.sort(ascending), 0.5);
19576 };
19577
19578 var merge = function(arrays) {
19579   var n = arrays.length,
19580       m,
19581       i = -1,
19582       j = 0,
19583       merged,
19584       array;
19585
19586   while (++i < n) j += arrays[i].length;
19587   merged = new Array(j);
19588
19589   while (--n >= 0) {
19590     array = arrays[n];
19591     m = array.length;
19592     while (--m >= 0) {
19593       merged[--j] = array[m];
19594     }
19595   }
19596
19597   return merged;
19598 };
19599
19600 var min = function(array, f) {
19601   var i = -1,
19602       n = array.length,
19603       a,
19604       b;
19605
19606   if (f == null) {
19607     while (++i < n) if ((b = array[i]) != null && b >= b) { a = b; break; }
19608     while (++i < n) if ((b = array[i]) != null && a > b) a = b;
19609   }
19610
19611   else {
19612     while (++i < n) if ((b = f(array[i], i, array)) != null && b >= b) { a = b; break; }
19613     while (++i < n) if ((b = f(array[i], i, array)) != null && a > b) a = b;
19614   }
19615
19616   return a;
19617 };
19618
19619 var pairs = function(array) {
19620   var i = 0, n = array.length - 1, p = array[0], pairs = new Array(n < 0 ? 0 : n);
19621   while (i < n) pairs[i] = [p, p = array[++i]];
19622   return pairs;
19623 };
19624
19625 var permute = function(array, indexes) {
19626   var i = indexes.length, permutes = new Array(i);
19627   while (i--) permutes[i] = array[indexes[i]];
19628   return permutes;
19629 };
19630
19631 var scan = function(array, compare) {
19632   if (!(n = array.length)) return;
19633   var i = 0,
19634       n,
19635       j = 0,
19636       xi,
19637       xj = array[j];
19638
19639   if (!compare) compare = ascending;
19640
19641   while (++i < n) if (compare(xi = array[i], xj) < 0 || compare(xj, xj) !== 0) xj = xi, j = i;
19642
19643   if (compare(xj, xj) === 0) return j;
19644 };
19645
19646 var shuffle = function(array, i0, i1) {
19647   var m = (i1 == null ? array.length : i1) - (i0 = i0 == null ? 0 : +i0),
19648       t,
19649       i;
19650
19651   while (m) {
19652     i = Math.random() * m-- | 0;
19653     t = array[m + i0];
19654     array[m + i0] = array[i + i0];
19655     array[i + i0] = t;
19656   }
19657
19658   return array;
19659 };
19660
19661 var sum = function(array, f) {
19662   var s = 0,
19663       n = array.length,
19664       a,
19665       i = -1;
19666
19667   if (f == null) {
19668     while (++i < n) if (a = +array[i]) s += a; // Note: zero and null are equivalent.
19669   }
19670
19671   else {
19672     while (++i < n) if (a = +f(array[i], i, array)) s += a;
19673   }
19674
19675   return s;
19676 };
19677
19678 var transpose = function(matrix) {
19679   if (!(n = matrix.length)) return [];
19680   for (var i = -1, m = min(matrix, length), transpose = new Array(m); ++i < m;) {
19681     for (var j = -1, n, row = transpose[i] = new Array(n); ++j < n;) {
19682       row[j] = matrix[j][i];
19683     }
19684   }
19685   return transpose;
19686 };
19687
19688 function length(d) {
19689   return d.length;
19690 }
19691
19692 var zip = function() {
19693   return transpose(arguments);
19694 };
19695
19696 var prefix = "$";
19697
19698 function Map() {}
19699
19700 Map.prototype = map$1.prototype = {
19701   constructor: Map,
19702   has: function(key) {
19703     return (prefix + key) in this;
19704   },
19705   get: function(key) {
19706     return this[prefix + key];
19707   },
19708   set: function(key, value) {
19709     this[prefix + key] = value;
19710     return this;
19711   },
19712   remove: function(key) {
19713     var property = prefix + key;
19714     return property in this && delete this[property];
19715   },
19716   clear: function() {
19717     for (var property in this) if (property[0] === prefix) delete this[property];
19718   },
19719   keys: function() {
19720     var keys = [];
19721     for (var property in this) if (property[0] === prefix) keys.push(property.slice(1));
19722     return keys;
19723   },
19724   values: function() {
19725     var values = [];
19726     for (var property in this) if (property[0] === prefix) values.push(this[property]);
19727     return values;
19728   },
19729   entries: function() {
19730     var entries = [];
19731     for (var property in this) if (property[0] === prefix) entries.push({key: property.slice(1), value: this[property]});
19732     return entries;
19733   },
19734   size: function() {
19735     var size = 0;
19736     for (var property in this) if (property[0] === prefix) ++size;
19737     return size;
19738   },
19739   empty: function() {
19740     for (var property in this) if (property[0] === prefix) return false;
19741     return true;
19742   },
19743   each: function(f) {
19744     for (var property in this) if (property[0] === prefix) f(this[property], property.slice(1), this);
19745   }
19746 };
19747
19748 function map$1(object, f) {
19749   var map = new Map;
19750
19751   // Copy constructor.
19752   if (object instanceof Map) object.each(function(value, key) { map.set(key, value); });
19753
19754   // Index array by numeric index or specified key function.
19755   else if (Array.isArray(object)) {
19756     var i = -1,
19757         n = object.length,
19758         o;
19759
19760     if (f == null) while (++i < n) map.set(i, object[i]);
19761     else while (++i < n) map.set(f(o = object[i], i, object), o);
19762   }
19763
19764   // Convert object to map.
19765   else if (object) for (var key in object) map.set(key, object[key]);
19766
19767   return map;
19768 }
19769
19770 var nest = function() {
19771   var keys = [],
19772       sortKeys = [],
19773       sortValues,
19774       rollup,
19775       nest;
19776
19777   function apply(array, depth, createResult, setResult) {
19778     if (depth >= keys.length) return rollup != null
19779         ? rollup(array) : (sortValues != null
19780         ? array.sort(sortValues)
19781         : array);
19782
19783     var i = -1,
19784         n = array.length,
19785         key = keys[depth++],
19786         keyValue,
19787         value,
19788         valuesByKey = map$1(),
19789         values,
19790         result = createResult();
19791
19792     while (++i < n) {
19793       if (values = valuesByKey.get(keyValue = key(value = array[i]) + "")) {
19794         values.push(value);
19795       } else {
19796         valuesByKey.set(keyValue, [value]);
19797       }
19798     }
19799
19800     valuesByKey.each(function(values, key) {
19801       setResult(result, key, apply(values, depth, createResult, setResult));
19802     });
19803
19804     return result;
19805   }
19806
19807   function entries(map, depth) {
19808     if (++depth > keys.length) return map;
19809     var array, sortKey = sortKeys[depth - 1];
19810     if (rollup != null && depth >= keys.length) array = map.entries();
19811     else array = [], map.each(function(v, k) { array.push({key: k, values: entries(v, depth)}); });
19812     return sortKey != null ? array.sort(function(a, b) { return sortKey(a.key, b.key); }) : array;
19813   }
19814
19815   return nest = {
19816     object: function(array) { return apply(array, 0, createObject, setObject); },
19817     map: function(array) { return apply(array, 0, createMap, setMap); },
19818     entries: function(array) { return entries(apply(array, 0, createMap, setMap), 0); },
19819     key: function(d) { keys.push(d); return nest; },
19820     sortKeys: function(order) { sortKeys[keys.length - 1] = order; return nest; },
19821     sortValues: function(order) { sortValues = order; return nest; },
19822     rollup: function(f) { rollup = f; return nest; }
19823   };
19824 };
19825
19826 function createObject() {
19827   return {};
19828 }
19829
19830 function setObject(object, key, value) {
19831   object[key] = value;
19832 }
19833
19834 function createMap() {
19835   return map$1();
19836 }
19837
19838 function setMap(map, key, value) {
19839   map.set(key, value);
19840 }
19841
19842 function Set() {}
19843
19844 var proto = map$1.prototype;
19845
19846 Set.prototype = set.prototype = {
19847   constructor: Set,
19848   has: proto.has,
19849   add: function(value) {
19850     value += "";
19851     this[prefix + value] = value;
19852     return this;
19853   },
19854   remove: proto.remove,
19855   clear: proto.clear,
19856   values: proto.keys,
19857   size: proto.size,
19858   empty: proto.empty,
19859   each: proto.each
19860 };
19861
19862 function set(object, f) {
19863   var set = new Set;
19864
19865   // Copy constructor.
19866   if (object instanceof Set) object.each(function(value) { set.add(value); });
19867
19868   // Otherwise, assume it’s an array.
19869   else if (object) {
19870     var i = -1, n = object.length;
19871     if (f == null) while (++i < n) set.add(object[i]);
19872     else while (++i < n) set.add(f(object[i], i, object));
19873   }
19874
19875   return set;
19876 }
19877
19878 var keys = function(map) {
19879   var keys = [];
19880   for (var key in map) keys.push(key);
19881   return keys;
19882 };
19883
19884 var values = function(map) {
19885   var values = [];
19886   for (var key in map) values.push(map[key]);
19887   return values;
19888 };
19889
19890 var entries = function(map) {
19891   var entries = [];
19892   for (var key in map) entries.push({key: key, value: map[key]});
19893   return entries;
19894 };
19895
19896 var uniform = function(min, max) {
19897   min = min == null ? 0 : +min;
19898   max = max == null ? 1 : +max;
19899   if (arguments.length === 1) max = min, min = 0;
19900   else max -= min;
19901   return function() {
19902     return Math.random() * max + min;
19903   };
19904 };
19905
19906 var normal = function(mu, sigma) {
19907   var x, r;
19908   mu = mu == null ? 0 : +mu;
19909   sigma = sigma == null ? 1 : +sigma;
19910   return function() {
19911     var y;
19912
19913     // If available, use the second previously-generated uniform random.
19914     if (x != null) y = x, x = null;
19915
19916     // Otherwise, generate a new x and y.
19917     else do {
19918       x = Math.random() * 2 - 1;
19919       y = Math.random() * 2 - 1;
19920       r = x * x + y * y;
19921     } while (!r || r > 1);
19922
19923     return mu + sigma * y * Math.sqrt(-2 * Math.log(r) / r);
19924   };
19925 };
19926
19927 var logNormal = function() {
19928   var randomNormal = normal.apply(this, arguments);
19929   return function() {
19930     return Math.exp(randomNormal());
19931   };
19932 };
19933
19934 var irwinHall = function(n) {
19935   return function() {
19936     for (var sum = 0, i = 0; i < n; ++i) sum += Math.random();
19937     return sum;
19938   };
19939 };
19940
19941 var bates = function(n) {
19942   var randomIrwinHall = irwinHall(n);
19943   return function() {
19944     return randomIrwinHall() / n;
19945   };
19946 };
19947
19948 var exponential = function(lambda) {
19949   return function() {
19950     return -Math.log(1 - Math.random()) / lambda;
19951   };
19952 };
19953
19954 function linear(t) {
19955   return +t;
19956 }
19957
19958 function quadIn(t) {
19959   return t * t;
19960 }
19961
19962 function quadOut(t) {
19963   return t * (2 - t);
19964 }
19965
19966 function quadInOut(t) {
19967   return ((t *= 2) <= 1 ? t * t : --t * (2 - t) + 1) / 2;
19968 }
19969
19970 function cubicIn(t) {
19971   return t * t * t;
19972 }
19973
19974 function cubicOut(t) {
19975   return --t * t * t + 1;
19976 }
19977
19978 function cubicInOut(t) {
19979   return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;
19980 }
19981
19982 var exponent = 3;
19983
19984 var polyIn = (function custom(e) {
19985   e = +e;
19986
19987   function polyIn(t) {
19988     return Math.pow(t, e);
19989   }
19990
19991   polyIn.exponent = custom;
19992
19993   return polyIn;
19994 })(exponent);
19995
19996 var polyOut = (function custom(e) {
19997   e = +e;
19998
19999   function polyOut(t) {
20000     return 1 - Math.pow(1 - t, e);
20001   }
20002
20003   polyOut.exponent = custom;
20004
20005   return polyOut;
20006 })(exponent);
20007
20008 var polyInOut = (function custom(e) {
20009   e = +e;
20010
20011   function polyInOut(t) {
20012     return ((t *= 2) <= 1 ? Math.pow(t, e) : 2 - Math.pow(2 - t, e)) / 2;
20013   }
20014
20015   polyInOut.exponent = custom;
20016
20017   return polyInOut;
20018 })(exponent);
20019
20020 var pi = Math.PI;
20021 var halfPi = pi / 2;
20022
20023 function sinIn(t) {
20024   return 1 - Math.cos(t * halfPi);
20025 }
20026
20027 function sinOut(t) {
20028   return Math.sin(t * halfPi);
20029 }
20030
20031 function sinInOut(t) {
20032   return (1 - Math.cos(pi * t)) / 2;
20033 }
20034
20035 function expIn(t) {
20036   return Math.pow(2, 10 * t - 10);
20037 }
20038
20039 function expOut(t) {
20040   return 1 - Math.pow(2, -10 * t);
20041 }
20042
20043 function expInOut(t) {
20044   return ((t *= 2) <= 1 ? Math.pow(2, 10 * t - 10) : 2 - Math.pow(2, 10 - 10 * t)) / 2;
20045 }
20046
20047 function circleIn(t) {
20048   return 1 - Math.sqrt(1 - t * t);
20049 }
20050
20051 function circleOut(t) {
20052   return Math.sqrt(1 - --t * t);
20053 }
20054
20055 function circleInOut(t) {
20056   return ((t *= 2) <= 1 ? 1 - Math.sqrt(1 - t * t) : Math.sqrt(1 - (t -= 2) * t) + 1) / 2;
20057 }
20058
20059 var b1 = 4 / 11;
20060 var b2 = 6 / 11;
20061 var b3 = 8 / 11;
20062 var b4 = 3 / 4;
20063 var b5 = 9 / 11;
20064 var b6 = 10 / 11;
20065 var b7 = 15 / 16;
20066 var b8 = 21 / 22;
20067 var b9 = 63 / 64;
20068 var b0 = 1 / b1 / b1;
20069
20070 function bounceIn(t) {
20071   return 1 - bounceOut(1 - t);
20072 }
20073
20074 function bounceOut(t) {
20075   return (t = +t) < b1 ? b0 * t * t : t < b3 ? b0 * (t -= b2) * t + b4 : t < b6 ? b0 * (t -= b5) * t + b7 : b0 * (t -= b8) * t + b9;
20076 }
20077
20078 function bounceInOut(t) {
20079   return ((t *= 2) <= 1 ? 1 - bounceOut(1 - t) : bounceOut(t - 1) + 1) / 2;
20080 }
20081
20082 var overshoot = 1.70158;
20083
20084 var backIn = (function custom(s) {
20085   s = +s;
20086
20087   function backIn(t) {
20088     return t * t * ((s + 1) * t - s);
20089   }
20090
20091   backIn.overshoot = custom;
20092
20093   return backIn;
20094 })(overshoot);
20095
20096 var backOut = (function custom(s) {
20097   s = +s;
20098
20099   function backOut(t) {
20100     return --t * t * ((s + 1) * t + s) + 1;
20101   }
20102
20103   backOut.overshoot = custom;
20104
20105   return backOut;
20106 })(overshoot);
20107
20108 var backInOut = (function custom(s) {
20109   s = +s;
20110
20111   function backInOut(t) {
20112     return ((t *= 2) < 1 ? t * t * ((s + 1) * t - s) : (t -= 2) * t * ((s + 1) * t + s) + 2) / 2;
20113   }
20114
20115   backInOut.overshoot = custom;
20116
20117   return backInOut;
20118 })(overshoot);
20119
20120 var tau = 2 * Math.PI;
20121 var amplitude = 1;
20122 var period = 0.3;
20123
20124 var elasticIn = (function custom(a, p) {
20125   var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
20126
20127   function elasticIn(t) {
20128     return a * Math.pow(2, 10 * --t) * Math.sin((s - t) / p);
20129   }
20130
20131   elasticIn.amplitude = function(a) { return custom(a, p * tau); };
20132   elasticIn.period = function(p) { return custom(a, p); };
20133
20134   return elasticIn;
20135 })(amplitude, period);
20136
20137 var elasticOut = (function custom(a, p) {
20138   var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
20139
20140   function elasticOut(t) {
20141     return 1 - a * Math.pow(2, -10 * (t = +t)) * Math.sin((t + s) / p);
20142   }
20143
20144   elasticOut.amplitude = function(a) { return custom(a, p * tau); };
20145   elasticOut.period = function(p) { return custom(a, p); };
20146
20147   return elasticOut;
20148 })(amplitude, period);
20149
20150 var elasticInOut = (function custom(a, p) {
20151   var s = Math.asin(1 / (a = Math.max(1, a))) * (p /= tau);
20152
20153   function elasticInOut(t) {
20154     return ((t = t * 2 - 1) < 0
20155         ? a * Math.pow(2, 10 * t) * Math.sin((s - t) / p)
20156         : 2 - a * Math.pow(2, -10 * t) * Math.sin((s + t) / p)) / 2;
20157   }
20158
20159   elasticInOut.amplitude = function(a) { return custom(a, p * tau); };
20160   elasticInOut.period = function(p) { return custom(a, p); };
20161
20162   return elasticInOut;
20163 })(amplitude, period);
20164
20165 var d3polygonArea = function(polygon) {
20166   var i = -1,
20167       n = polygon.length,
20168       a,
20169       b = polygon[n - 1],
20170       area = 0;
20171
20172   while (++i < n) {
20173     a = b;
20174     b = polygon[i];
20175     area += a[1] * b[0] - a[0] * b[1];
20176   }
20177
20178   return area / 2;
20179 };
20180
20181 var d3polygonCentroid = function(polygon) {
20182   var i = -1,
20183       n = polygon.length,
20184       x = 0,
20185       y = 0,
20186       a,
20187       b = polygon[n - 1],
20188       c,
20189       k = 0;
20190
20191   while (++i < n) {
20192     a = b;
20193     b = polygon[i];
20194     k += c = a[0] * b[1] - b[0] * a[1];
20195     x += (a[0] + b[0]) * c;
20196     y += (a[1] + b[1]) * c;
20197   }
20198
20199   return k *= 3, [x / k, y / k];
20200 };
20201
20202 // Returns the 2D cross product of AB and AC vectors, i.e., the z-component of
20203 // the 3D cross product in a quadrant I Cartesian coordinate system (+x is
20204 // right, +y is up). Returns a positive value if ABC is counter-clockwise,
20205 // negative if clockwise, and zero if the points are collinear.
20206 var cross = function(a, b, c) {
20207   return (b[0] - a[0]) * (c[1] - a[1]) - (b[1] - a[1]) * (c[0] - a[0]);
20208 };
20209
20210 function lexicographicOrder(a, b) {
20211   return a[0] - b[0] || a[1] - b[1];
20212 }
20213
20214 // Computes the upper convex hull per the monotone chain algorithm.
20215 // Assumes points.length >= 3, is sorted by x, unique in y.
20216 // Returns an array of indices into points in left-to-right order.
20217 function computeUpperHullIndexes(points) {
20218   var n = points.length,
20219       indexes = [0, 1],
20220       size = 2;
20221
20222   for (var i = 2; i < n; ++i) {
20223     while (size > 1 && cross(points[indexes[size - 2]], points[indexes[size - 1]], points[i]) <= 0) --size;
20224     indexes[size++] = i;
20225   }
20226
20227   return indexes.slice(0, size); // remove popped points
20228 }
20229
20230 var d3polygonHull = function(points) {
20231   if ((n = points.length) < 3) return null;
20232
20233   var i,
20234       n,
20235       sortedPoints = new Array(n),
20236       flippedPoints = new Array(n);
20237
20238   for (i = 0; i < n; ++i) sortedPoints[i] = [+points[i][0], +points[i][1], i];
20239   sortedPoints.sort(lexicographicOrder);
20240   for (i = 0; i < n; ++i) flippedPoints[i] = [sortedPoints[i][0], -sortedPoints[i][1]];
20241
20242   var upperIndexes = computeUpperHullIndexes(sortedPoints),
20243       lowerIndexes = computeUpperHullIndexes(flippedPoints);
20244
20245   // Construct the hull polygon, removing possible duplicate endpoints.
20246   var skipLeft = lowerIndexes[0] === upperIndexes[0],
20247       skipRight = lowerIndexes[lowerIndexes.length - 1] === upperIndexes[upperIndexes.length - 1],
20248       hull = [];
20249
20250   // Add upper hull in right-to-l order.
20251   // Then add lower hull in left-to-right order.
20252   for (i = upperIndexes.length - 1; i >= 0; --i) hull.push(points[sortedPoints[upperIndexes[i]][2]]);
20253   for (i = +skipLeft; i < lowerIndexes.length - skipRight; ++i) hull.push(points[sortedPoints[lowerIndexes[i]][2]]);
20254
20255   return hull;
20256 };
20257
20258 var contains = function(polygon, point) {
20259   var n = polygon.length,
20260       p = polygon[n - 1],
20261       x = point[0], y = point[1],
20262       x0 = p[0], y0 = p[1],
20263       x1, y1,
20264       inside = false;
20265
20266   for (var i = 0; i < n; ++i) {
20267     p = polygon[i], x1 = p[0], y1 = p[1];
20268     if (((y1 > y) !== (y0 > y)) && (x < (x0 - x1) * (y - y1) / (y0 - y1) + x1)) inside = !inside;
20269     x0 = x1, y0 = y1;
20270   }
20271
20272   return inside;
20273 };
20274
20275 var length$1 = function(polygon) {
20276   var i = -1,
20277       n = polygon.length,
20278       b = polygon[n - 1],
20279       xa,
20280       ya,
20281       xb = b[0],
20282       yb = b[1],
20283       perimeter = 0;
20284
20285   while (++i < n) {
20286     xa = xb;
20287     ya = yb;
20288     b = polygon[i];
20289     xb = b[0];
20290     yb = b[1];
20291     xa -= xb;
20292     ya -= yb;
20293     perimeter += Math.sqrt(xa * xa + ya * ya);
20294   }
20295
20296   return perimeter;
20297 };
20298
20299 var pi$1 = Math.PI;
20300 var tau$1 = 2 * pi$1;
20301 var epsilon = 1e-6;
20302 var tauEpsilon = tau$1 - epsilon;
20303
20304 function Path() {
20305   this._x0 = this._y0 = // start of current subpath
20306   this._x1 = this._y1 = null; // end of current subpath
20307   this._ = [];
20308 }
20309
20310 function path() {
20311   return new Path;
20312 }
20313
20314 Path.prototype = path.prototype = {
20315   constructor: Path,
20316   moveTo: function(x, y) {
20317     this._.push("M", this._x0 = this._x1 = +x, ",", this._y0 = this._y1 = +y);
20318   },
20319   closePath: function() {
20320     if (this._x1 !== null) {
20321       this._x1 = this._x0, this._y1 = this._y0;
20322       this._.push("Z");
20323     }
20324   },
20325   lineTo: function(x, y) {
20326     this._.push("L", this._x1 = +x, ",", this._y1 = +y);
20327   },
20328   quadraticCurveTo: function(x1, y1, x, y) {
20329     this._.push("Q", +x1, ",", +y1, ",", this._x1 = +x, ",", this._y1 = +y);
20330   },
20331   bezierCurveTo: function(x1, y1, x2, y2, x, y) {
20332     this._.push("C", +x1, ",", +y1, ",", +x2, ",", +y2, ",", this._x1 = +x, ",", this._y1 = +y);
20333   },
20334   arcTo: function(x1, y1, x2, y2, r) {
20335     x1 = +x1, y1 = +y1, x2 = +x2, y2 = +y2, r = +r;
20336     var x0 = this._x1,
20337         y0 = this._y1,
20338         x21 = x2 - x1,
20339         y21 = y2 - y1,
20340         x01 = x0 - x1,
20341         y01 = y0 - y1,
20342         l01_2 = x01 * x01 + y01 * y01;
20343
20344     // Is the radius negative? Error.
20345     if (r < 0) throw new Error("negative radius: " + r);
20346
20347     // Is this path empty? Move to (x1,y1).
20348     if (this._x1 === null) {
20349       this._.push(
20350         "M", this._x1 = x1, ",", this._y1 = y1
20351       );
20352     }
20353
20354     // Or, is (x1,y1) coincident with (x0,y0)? Do nothing.
20355     else if (!(l01_2 > epsilon)) {}
20356
20357     // Or, are (x0,y0), (x1,y1) and (x2,y2) collinear?
20358     // Equivalently, is (x1,y1) coincident with (x2,y2)?
20359     // Or, is the radius zero? Line to (x1,y1).
20360     else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon) || !r) {
20361       this._.push(
20362         "L", this._x1 = x1, ",", this._y1 = y1
20363       );
20364     }
20365
20366     // Otherwise, draw an arc!
20367     else {
20368       var x20 = x2 - x0,
20369           y20 = y2 - y0,
20370           l21_2 = x21 * x21 + y21 * y21,
20371           l20_2 = x20 * x20 + y20 * y20,
20372           l21 = Math.sqrt(l21_2),
20373           l01 = Math.sqrt(l01_2),
20374           l = r * Math.tan((pi$1 - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2),
20375           t01 = l / l01,
20376           t21 = l / l21;
20377
20378       // If the start tangent is not coincident with (x0,y0), line to.
20379       if (Math.abs(t01 - 1) > epsilon) {
20380         this._.push(
20381           "L", x1 + t01 * x01, ",", y1 + t01 * y01
20382         );
20383       }
20384
20385       this._.push(
20386         "A", r, ",", r, ",0,0,", +(y01 * x20 > x01 * y20), ",", this._x1 = x1 + t21 * x21, ",", this._y1 = y1 + t21 * y21
20387       );
20388     }
20389   },
20390   arc: function(x, y, r, a0, a1, ccw) {
20391     x = +x, y = +y, r = +r;
20392     var dx = r * Math.cos(a0),
20393         dy = r * Math.sin(a0),
20394         x0 = x + dx,
20395         y0 = y + dy,
20396         cw = 1 ^ ccw,
20397         da = ccw ? a0 - a1 : a1 - a0;
20398
20399     // Is the radius negative? Error.
20400     if (r < 0) throw new Error("negative radius: " + r);
20401
20402     // Is this path empty? Move to (x0,y0).
20403     if (this._x1 === null) {
20404       this._.push(
20405         "M", x0, ",", y0
20406       );
20407     }
20408
20409     // Or, is (x0,y0) not coincident with the previous point? Line to (x0,y0).
20410     else if (Math.abs(this._x1 - x0) > epsilon || Math.abs(this._y1 - y0) > epsilon) {
20411       this._.push(
20412         "L", x0, ",", y0
20413       );
20414     }
20415
20416     // Is this arc empty? We’re done.
20417     if (!r) return;
20418
20419     // Is this a complete circle? Draw two arcs to complete the circle.
20420     if (da > tauEpsilon) {
20421       this._.push(
20422         "A", r, ",", r, ",0,1,", cw, ",", x - dx, ",", y - dy,
20423         "A", r, ",", r, ",0,1,", cw, ",", this._x1 = x0, ",", this._y1 = y0
20424       );
20425     }
20426
20427     // Otherwise, draw an arc!
20428     else {
20429       if (da < 0) da = da % tau$1 + tau$1;
20430       this._.push(
20431         "A", r, ",", r, ",0,", +(da >= pi$1), ",", cw, ",", this._x1 = x + r * Math.cos(a1), ",", this._y1 = y + r * Math.sin(a1)
20432       );
20433     }
20434   },
20435   rect: function(x, y, w, h) {
20436     this._.push("M", this._x0 = this._x1 = +x, ",", this._y0 = this._y1 = +y, "h", +w, "v", +h, "h", -w, "Z");
20437   },
20438   toString: function() {
20439     return this._.join("");
20440   }
20441 };
20442
20443 var tree_add = function(d) {
20444   var x = +this._x.call(null, d),
20445       y = +this._y.call(null, d);
20446   return add(this.cover(x, y), x, y, d);
20447 };
20448
20449 function add(tree, x, y, d) {
20450   if (isNaN(x) || isNaN(y)) return tree; // ignore invalid points
20451
20452   var parent,
20453       node = tree._root,
20454       leaf = {data: d},
20455       x0 = tree._x0,
20456       y0 = tree._y0,
20457       x1 = tree._x1,
20458       y1 = tree._y1,
20459       xm,
20460       ym,
20461       xp,
20462       yp,
20463       right,
20464       bottom,
20465       i,
20466       j;
20467
20468   // If the tree is empty, initialize the root as a leaf.
20469   if (!node) return tree._root = leaf, tree;
20470
20471   // Find the existing leaf for the new point, or add it.
20472   while (node.length) {
20473     if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
20474     if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
20475     if (parent = node, !(node = node[i = bottom << 1 | right])) return parent[i] = leaf, tree;
20476   }
20477
20478   // Is the new point is exactly coincident with the existing point?
20479   xp = +tree._x.call(null, node.data);
20480   yp = +tree._y.call(null, node.data);
20481   if (x === xp && y === yp) return leaf.next = node, parent ? parent[i] = leaf : tree._root = leaf, tree;
20482
20483   // Otherwise, split the leaf node until the old and new point are separated.
20484   do {
20485     parent = parent ? parent[i] = new Array(4) : tree._root = new Array(4);
20486     if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
20487     if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
20488   } while ((i = bottom << 1 | right) === (j = (yp >= ym) << 1 | (xp >= xm)));
20489   return parent[j] = node, parent[i] = leaf, tree;
20490 }
20491
20492 function addAll(data) {
20493   var d, i, n = data.length,
20494       x,
20495       y,
20496       xz = new Array(n),
20497       yz = new Array(n),
20498       x0 = Infinity,
20499       y0 = Infinity,
20500       x1 = -Infinity,
20501       y1 = -Infinity;
20502
20503   // Compute the points and their extent.
20504   for (i = 0; i < n; ++i) {
20505     if (isNaN(x = +this._x.call(null, d = data[i])) || isNaN(y = +this._y.call(null, d))) continue;
20506     xz[i] = x;
20507     yz[i] = y;
20508     if (x < x0) x0 = x;
20509     if (x > x1) x1 = x;
20510     if (y < y0) y0 = y;
20511     if (y > y1) y1 = y;
20512   }
20513
20514   // If there were no (valid) points, inherit the existing extent.
20515   if (x1 < x0) x0 = this._x0, x1 = this._x1;
20516   if (y1 < y0) y0 = this._y0, y1 = this._y1;
20517
20518   // Expand the tree to cover the new points.
20519   this.cover(x0, y0).cover(x1, y1);
20520
20521   // Add the new points.
20522   for (i = 0; i < n; ++i) {
20523     add(this, xz[i], yz[i], data[i]);
20524   }
20525
20526   return this;
20527 }
20528
20529 var tree_cover = function(x, y) {
20530   if (isNaN(x = +x) || isNaN(y = +y)) return this; // ignore invalid points
20531
20532   var x0 = this._x0,
20533       y0 = this._y0,
20534       x1 = this._x1,
20535       y1 = this._y1;
20536
20537   // If the quadtree has no extent, initialize them.
20538   // Integer extent are necessary so that if we later double the extent,
20539   // the existing quadrant boundaries don’t change due to floating point error!
20540   if (isNaN(x0)) {
20541     x1 = (x0 = Math.floor(x)) + 1;
20542     y1 = (y0 = Math.floor(y)) + 1;
20543   }
20544
20545   // Otherwise, double repeatedly to cover.
20546   else if (x0 > x || x > x1 || y0 > y || y > y1) {
20547     var z = x1 - x0,
20548         node = this._root,
20549         parent,
20550         i;
20551
20552     switch (i = (y < (y0 + y1) / 2) << 1 | (x < (x0 + x1) / 2)) {
20553       case 0: {
20554         do parent = new Array(4), parent[i] = node, node = parent;
20555         while (z *= 2, x1 = x0 + z, y1 = y0 + z, x > x1 || y > y1);
20556         break;
20557       }
20558       case 1: {
20559         do parent = new Array(4), parent[i] = node, node = parent;
20560         while (z *= 2, x0 = x1 - z, y1 = y0 + z, x0 > x || y > y1);
20561         break;
20562       }
20563       case 2: {
20564         do parent = new Array(4), parent[i] = node, node = parent;
20565         while (z *= 2, x1 = x0 + z, y0 = y1 - z, x > x1 || y0 > y);
20566         break;
20567       }
20568       case 3: {
20569         do parent = new Array(4), parent[i] = node, node = parent;
20570         while (z *= 2, x0 = x1 - z, y0 = y1 - z, x0 > x || y0 > y);
20571         break;
20572       }
20573     }
20574
20575     if (this._root && this._root.length) this._root = node;
20576   }
20577
20578   // If the quadtree covers the point already, just return.
20579   else return this;
20580
20581   this._x0 = x0;
20582   this._y0 = y0;
20583   this._x1 = x1;
20584   this._y1 = y1;
20585   return this;
20586 };
20587
20588 var tree_data = function() {
20589   var data = [];
20590   this.visit(function(node) {
20591     if (!node.length) do data.push(node.data); while (node = node.next)
20592   });
20593   return data;
20594 };
20595
20596 var tree_extent = function(_) {
20597   return arguments.length
20598       ? this.cover(+_[0][0], +_[0][1]).cover(+_[1][0], +_[1][1])
20599       : isNaN(this._x0) ? undefined : [[this._x0, this._y0], [this._x1, this._y1]];
20600 };
20601
20602 var Quad = function(node, x0, y0, x1, y1) {
20603   this.node = node;
20604   this.x0 = x0;
20605   this.y0 = y0;
20606   this.x1 = x1;
20607   this.y1 = y1;
20608 };
20609
20610 var tree_find = function(x, y, radius) {
20611   var data,
20612       x0 = this._x0,
20613       y0 = this._y0,
20614       x1,
20615       y1,
20616       x2,
20617       y2,
20618       x3 = this._x1,
20619       y3 = this._y1,
20620       quads = [],
20621       node = this._root,
20622       q,
20623       i;
20624
20625   if (node) quads.push(new Quad(node, x0, y0, x3, y3));
20626   if (radius == null) radius = Infinity;
20627   else {
20628     x0 = x - radius, y0 = y - radius;
20629     x3 = x + radius, y3 = y + radius;
20630     radius *= radius;
20631   }
20632
20633   while (q = quads.pop()) {
20634
20635     // Stop searching if this quadrant can’t contain a closer node.
20636     if (!(node = q.node)
20637         || (x1 = q.x0) > x3
20638         || (y1 = q.y0) > y3
20639         || (x2 = q.x1) < x0
20640         || (y2 = q.y1) < y0) continue;
20641
20642     // Bisect the current quadrant.
20643     if (node.length) {
20644       var xm = (x1 + x2) / 2,
20645           ym = (y1 + y2) / 2;
20646
20647       quads.push(
20648         new Quad(node[3], xm, ym, x2, y2),
20649         new Quad(node[2], x1, ym, xm, y2),
20650         new Quad(node[1], xm, y1, x2, ym),
20651         new Quad(node[0], x1, y1, xm, ym)
20652       );
20653
20654       // Visit the closest quadrant first.
20655       if (i = (y >= ym) << 1 | (x >= xm)) {
20656         q = quads[quads.length - 1];
20657         quads[quads.length - 1] = quads[quads.length - 1 - i];
20658         quads[quads.length - 1 - i] = q;
20659       }
20660     }
20661
20662     // Visit this point. (Visiting coincident points isn’t necessary!)
20663     else {
20664       var dx = x - +this._x.call(null, node.data),
20665           dy = y - +this._y.call(null, node.data),
20666           d2 = dx * dx + dy * dy;
20667       if (d2 < radius) {
20668         var d = Math.sqrt(radius = d2);
20669         x0 = x - d, y0 = y - d;
20670         x3 = x + d, y3 = y + d;
20671         data = node.data;
20672       }
20673     }
20674   }
20675
20676   return data;
20677 };
20678
20679 var tree_remove = function(d) {
20680   if (isNaN(x = +this._x.call(null, d)) || isNaN(y = +this._y.call(null, d))) return this; // ignore invalid points
20681
20682   var parent,
20683       node = this._root,
20684       retainer,
20685       previous,
20686       next,
20687       x0 = this._x0,
20688       y0 = this._y0,
20689       x1 = this._x1,
20690       y1 = this._y1,
20691       x,
20692       y,
20693       xm,
20694       ym,
20695       right,
20696       bottom,
20697       i,
20698       j;
20699
20700   // If the tree is empty, initialize the root as a leaf.
20701   if (!node) return this;
20702
20703   // Find the leaf node for the point.
20704   // While descending, also retain the deepest parent with a non-removed sibling.
20705   if (node.length) while (true) {
20706     if (right = x >= (xm = (x0 + x1) / 2)) x0 = xm; else x1 = xm;
20707     if (bottom = y >= (ym = (y0 + y1) / 2)) y0 = ym; else y1 = ym;
20708     if (!(parent = node, node = node[i = bottom << 1 | right])) return this;
20709     if (!node.length) break;
20710     if (parent[(i + 1) & 3] || parent[(i + 2) & 3] || parent[(i + 3) & 3]) retainer = parent, j = i;
20711   }
20712
20713   // Find the point to remove.
20714   while (node.data !== d) if (!(previous = node, node = node.next)) return this;
20715   if (next = node.next) delete node.next;
20716
20717   // If there are multiple coincident points, remove just the point.
20718   if (previous) return (next ? previous.next = next : delete previous.next), this;
20719
20720   // If this is the root point, remove it.
20721   if (!parent) return this._root = next, this;
20722
20723   // Remove this leaf.
20724   next ? parent[i] = next : delete parent[i];
20725
20726   // If the parent now contains exactly one leaf, collapse superfluous parents.
20727   if ((node = parent[0] || parent[1] || parent[2] || parent[3])
20728       && node === (parent[3] || parent[2] || parent[1] || parent[0])
20729       && !node.length) {
20730     if (retainer) retainer[j] = node;
20731     else this._root = node;
20732   }
20733
20734   return this;
20735 };
20736
20737 function removeAll(data) {
20738   for (var i = 0, n = data.length; i < n; ++i) this.remove(data[i]);
20739   return this;
20740 }
20741
20742 var tree_root = function() {
20743   return this._root;
20744 };
20745
20746 var tree_size = function() {
20747   var size = 0;
20748   this.visit(function(node) {
20749     if (!node.length) do ++size; while (node = node.next)
20750   });
20751   return size;
20752 };
20753
20754 var tree_visit = function(callback) {
20755   var quads = [], q, node = this._root, child, x0, y0, x1, y1;
20756   if (node) quads.push(new Quad(node, this._x0, this._y0, this._x1, this._y1));
20757   while (q = quads.pop()) {
20758     if (!callback(node = q.node, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1) && node.length) {
20759       var xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;
20760       if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1));
20761       if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1));
20762       if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym));
20763       if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym));
20764     }
20765   }
20766   return this;
20767 };
20768
20769 var tree_visitAfter = function(callback) {
20770   var quads = [], next = [], q;
20771   if (this._root) quads.push(new Quad(this._root, this._x0, this._y0, this._x1, this._y1));
20772   while (q = quads.pop()) {
20773     var node = q.node;
20774     if (node.length) {
20775       var child, x0 = q.x0, y0 = q.y0, x1 = q.x1, y1 = q.y1, xm = (x0 + x1) / 2, ym = (y0 + y1) / 2;
20776       if (child = node[0]) quads.push(new Quad(child, x0, y0, xm, ym));
20777       if (child = node[1]) quads.push(new Quad(child, xm, y0, x1, ym));
20778       if (child = node[2]) quads.push(new Quad(child, x0, ym, xm, y1));
20779       if (child = node[3]) quads.push(new Quad(child, xm, ym, x1, y1));
20780     }
20781     next.push(q);
20782   }
20783   while (q = next.pop()) {
20784     callback(q.node, q.x0, q.y0, q.x1, q.y1);
20785   }
20786   return this;
20787 };
20788
20789 function defaultX(d) {
20790   return d[0];
20791 }
20792
20793 var tree_x = function(_) {
20794   return arguments.length ? (this._x = _, this) : this._x;
20795 };
20796
20797 function defaultY(d) {
20798   return d[1];
20799 }
20800
20801 var tree_y = function(_) {
20802   return arguments.length ? (this._y = _, this) : this._y;
20803 };
20804
20805 function quadtree(nodes, x, y) {
20806   var tree = new Quadtree(x == null ? defaultX : x, y == null ? defaultY : y, NaN, NaN, NaN, NaN);
20807   return nodes == null ? tree : tree.addAll(nodes);
20808 }
20809
20810 function Quadtree(x, y, x0, y0, x1, y1) {
20811   this._x = x;
20812   this._y = y;
20813   this._x0 = x0;
20814   this._y0 = y0;
20815   this._x1 = x1;
20816   this._y1 = y1;
20817   this._root = undefined;
20818 }
20819
20820 function leaf_copy(leaf) {
20821   var copy = {data: leaf.data}, next = copy;
20822   while (leaf = leaf.next) next = next.next = {data: leaf.data};
20823   return copy;
20824 }
20825
20826 var treeProto = quadtree.prototype = Quadtree.prototype;
20827
20828 treeProto.copy = function() {
20829   var copy = new Quadtree(this._x, this._y, this._x0, this._y0, this._x1, this._y1),
20830       node = this._root,
20831       nodes,
20832       child;
20833
20834   if (!node) return copy;
20835
20836   if (!node.length) return copy._root = leaf_copy(node), copy;
20837
20838   nodes = [{source: node, target: copy._root = new Array(4)}];
20839   while (node = nodes.pop()) {
20840     for (var i = 0; i < 4; ++i) {
20841       if (child = node.source[i]) {
20842         if (child.length) nodes.push({source: child, target: node.target[i] = new Array(4)});
20843         else node.target[i] = leaf_copy(child);
20844       }
20845     }
20846   }
20847
20848   return copy;
20849 };
20850
20851 treeProto.add = tree_add;
20852 treeProto.addAll = addAll;
20853 treeProto.cover = tree_cover;
20854 treeProto.data = tree_data;
20855 treeProto.extent = tree_extent;
20856 treeProto.find = tree_find;
20857 treeProto.remove = tree_remove;
20858 treeProto.removeAll = removeAll;
20859 treeProto.root = tree_root;
20860 treeProto.size = tree_size;
20861 treeProto.visit = tree_visit;
20862 treeProto.visitAfter = tree_visitAfter;
20863 treeProto.x = tree_x;
20864 treeProto.y = tree_y;
20865
20866 var slice$1 = [].slice;
20867
20868 var noabort = {};
20869
20870 function Queue(size) {
20871   if (!(size >= 1)) throw new Error;
20872   this._size = size;
20873   this._call =
20874   this._error = null;
20875   this._tasks = [];
20876   this._data = [];
20877   this._waiting =
20878   this._active =
20879   this._ended =
20880   this._start = 0; // inside a synchronous task callback?
20881 }
20882
20883 Queue.prototype = queue.prototype = {
20884   constructor: Queue,
20885   defer: function(callback) {
20886     if (typeof callback !== "function" || this._call) throw new Error;
20887     if (this._error != null) return this;
20888     var t = slice$1.call(arguments, 1);
20889     t.push(callback);
20890     ++this._waiting, this._tasks.push(t);
20891     poke(this);
20892     return this;
20893   },
20894   abort: function() {
20895     if (this._error == null) abort(this, new Error("abort"));
20896     return this;
20897   },
20898   await: function(callback) {
20899     if (typeof callback !== "function" || this._call) throw new Error;
20900     this._call = function(error, results) { callback.apply(null, [error].concat(results)); };
20901     maybeNotify(this);
20902     return this;
20903   },
20904   awaitAll: function(callback) {
20905     if (typeof callback !== "function" || this._call) throw new Error;
20906     this._call = callback;
20907     maybeNotify(this);
20908     return this;
20909   }
20910 };
20911
20912 function poke(q) {
20913   if (!q._start) {
20914     try { start(q); } // let the current task complete
20915     catch (e) {
20916       if (q._tasks[q._ended + q._active - 1]) abort(q, e); // task errored synchronously
20917       else if (!q._data) throw e; // await callback errored synchronously
20918     }
20919   }
20920 }
20921
20922 function start(q) {
20923   while (q._start = q._waiting && q._active < q._size) {
20924     var i = q._ended + q._active,
20925         t = q._tasks[i],
20926         j = t.length - 1,
20927         c = t[j];
20928     t[j] = end(q, i);
20929     --q._waiting, ++q._active;
20930     t = c.apply(null, t);
20931     if (!q._tasks[i]) continue; // task finished synchronously
20932     q._tasks[i] = t || noabort;
20933   }
20934 }
20935
20936 function end(q, i) {
20937   return function(e, r) {
20938     if (!q._tasks[i]) return; // ignore multiple callbacks
20939     --q._active, ++q._ended;
20940     q._tasks[i] = null;
20941     if (q._error != null) return; // ignore secondary errors
20942     if (e != null) {
20943       abort(q, e);
20944     } else {
20945       q._data[i] = r;
20946       if (q._waiting) poke(q);
20947       else maybeNotify(q);
20948     }
20949   };
20950 }
20951
20952 function abort(q, e) {
20953   var i = q._tasks.length, t;
20954   q._error = e; // ignore active callbacks
20955   q._data = undefined; // allow gc
20956   q._waiting = NaN; // prevent starting
20957
20958   while (--i >= 0) {
20959     if (t = q._tasks[i]) {
20960       q._tasks[i] = null;
20961       if (t.abort) {
20962         try { t.abort(); }
20963         catch (e) { /* ignore */ }
20964       }
20965     }
20966   }
20967
20968   q._active = NaN; // allow notification
20969   maybeNotify(q);
20970 }
20971
20972 function maybeNotify(q) {
20973   if (!q._active && q._call) {
20974     var d = q._data;
20975     q._data = undefined; // allow gc
20976     q._call(q._error, d);
20977   }
20978 }
20979
20980 function queue(concurrency) {
20981   return new Queue(arguments.length ? +concurrency : Infinity);
20982 }
20983
20984 var constant$2 = function(x) {
20985   return function constant() {
20986     return x;
20987   };
20988 };
20989
20990 var epsilon$1 = 1e-12;
20991 var pi$2 = Math.PI;
20992 var halfPi$1 = pi$2 / 2;
20993 var tau$2 = 2 * pi$2;
20994
20995 function arcInnerRadius(d) {
20996   return d.innerRadius;
20997 }
20998
20999 function arcOuterRadius(d) {
21000   return d.outerRadius;
21001 }
21002
21003 function arcStartAngle(d) {
21004   return d.startAngle;
21005 }
21006
21007 function arcEndAngle(d) {
21008   return d.endAngle;
21009 }
21010
21011 function arcPadAngle(d) {
21012   return d && d.padAngle; // Note: optional!
21013 }
21014
21015 function asin(x) {
21016   return x >= 1 ? halfPi$1 : x <= -1 ? -halfPi$1 : Math.asin(x);
21017 }
21018
21019 function intersect(x0, y0, x1, y1, x2, y2, x3, y3) {
21020   var x10 = x1 - x0, y10 = y1 - y0,
21021       x32 = x3 - x2, y32 = y3 - y2,
21022       t = (x32 * (y0 - y2) - y32 * (x0 - x2)) / (y32 * x10 - x32 * y10);
21023   return [x0 + t * x10, y0 + t * y10];
21024 }
21025
21026 // Compute perpendicular offset line of length rc.
21027 // http://mathworld.wolfram.com/Circle-LineIntersection.html
21028 function cornerTangents(x0, y0, x1, y1, r1, rc, cw) {
21029   var x01 = x0 - x1,
21030       y01 = y0 - y1,
21031       lo = (cw ? rc : -rc) / Math.sqrt(x01 * x01 + y01 * y01),
21032       ox = lo * y01,
21033       oy = -lo * x01,
21034       x11 = x0 + ox,
21035       y11 = y0 + oy,
21036       x10 = x1 + ox,
21037       y10 = y1 + oy,
21038       x00 = (x11 + x10) / 2,
21039       y00 = (y11 + y10) / 2,
21040       dx = x10 - x11,
21041       dy = y10 - y11,
21042       d2 = dx * dx + dy * dy,
21043       r = r1 - rc,
21044       D = x11 * y10 - x10 * y11,
21045       d = (dy < 0 ? -1 : 1) * Math.sqrt(Math.max(0, r * r * d2 - D * D)),
21046       cx0 = (D * dy - dx * d) / d2,
21047       cy0 = (-D * dx - dy * d) / d2,
21048       cx1 = (D * dy + dx * d) / d2,
21049       cy1 = (-D * dx + dy * d) / d2,
21050       dx0 = cx0 - x00,
21051       dy0 = cy0 - y00,
21052       dx1 = cx1 - x00,
21053       dy1 = cy1 - y00;
21054
21055   // Pick the closer of the two intersection points.
21056   // TODO Is there a faster way to determine which intersection to use?
21057   if (dx0 * dx0 + dy0 * dy0 > dx1 * dx1 + dy1 * dy1) cx0 = cx1, cy0 = cy1;
21058
21059   return {
21060     cx: cx0,
21061     cy: cy0,
21062     x01: -ox,
21063     y01: -oy,
21064     x11: cx0 * (r1 / r - 1),
21065     y11: cy0 * (r1 / r - 1)
21066   };
21067 }
21068
21069 var arc = function() {
21070   var innerRadius = arcInnerRadius,
21071       outerRadius = arcOuterRadius,
21072       cornerRadius = constant$2(0),
21073       padRadius = null,
21074       startAngle = arcStartAngle,
21075       endAngle = arcEndAngle,
21076       padAngle = arcPadAngle,
21077       context = null;
21078
21079   function arc() {
21080     var buffer,
21081         r,
21082         r0 = +innerRadius.apply(this, arguments),
21083         r1 = +outerRadius.apply(this, arguments),
21084         a0 = startAngle.apply(this, arguments) - halfPi$1,
21085         a1 = endAngle.apply(this, arguments) - halfPi$1,
21086         da = Math.abs(a1 - a0),
21087         cw = a1 > a0;
21088
21089     if (!context) context = buffer = path();
21090
21091     // Ensure that the outer radius is always larger than the inner radius.
21092     if (r1 < r0) r = r1, r1 = r0, r0 = r;
21093
21094     // Is it a point?
21095     if (!(r1 > epsilon$1)) context.moveTo(0, 0);
21096
21097     // Or is it a circle or annulus?
21098     else if (da > tau$2 - epsilon$1) {
21099       context.moveTo(r1 * Math.cos(a0), r1 * Math.sin(a0));
21100       context.arc(0, 0, r1, a0, a1, !cw);
21101       if (r0 > epsilon$1) {
21102         context.moveTo(r0 * Math.cos(a1), r0 * Math.sin(a1));
21103         context.arc(0, 0, r0, a1, a0, cw);
21104       }
21105     }
21106
21107     // Or is it a circular or annular sector?
21108     else {
21109       var a01 = a0,
21110           a11 = a1,
21111           a00 = a0,
21112           a10 = a1,
21113           da0 = da,
21114           da1 = da,
21115           ap = padAngle.apply(this, arguments) / 2,
21116           rp = (ap > epsilon$1) && (padRadius ? +padRadius.apply(this, arguments) : Math.sqrt(r0 * r0 + r1 * r1)),
21117           rc = Math.min(Math.abs(r1 - r0) / 2, +cornerRadius.apply(this, arguments)),
21118           rc0 = rc,
21119           rc1 = rc,
21120           t0,
21121           t1;
21122
21123       // Apply padding? Note that since r1 ≥ r0, da1 ≥ da0.
21124       if (rp > epsilon$1) {
21125         var p0 = asin(rp / r0 * Math.sin(ap)),
21126             p1 = asin(rp / r1 * Math.sin(ap));
21127         if ((da0 -= p0 * 2) > epsilon$1) p0 *= (cw ? 1 : -1), a00 += p0, a10 -= p0;
21128         else da0 = 0, a00 = a10 = (a0 + a1) / 2;
21129         if ((da1 -= p1 * 2) > epsilon$1) p1 *= (cw ? 1 : -1), a01 += p1, a11 -= p1;
21130         else da1 = 0, a01 = a11 = (a0 + a1) / 2;
21131       }
21132
21133       var x01 = r1 * Math.cos(a01),
21134           y01 = r1 * Math.sin(a01),
21135           x10 = r0 * Math.cos(a10),
21136           y10 = r0 * Math.sin(a10);
21137
21138       // Apply rounded corners?
21139       if (rc > epsilon$1) {
21140         var x11 = r1 * Math.cos(a11),
21141             y11 = r1 * Math.sin(a11),
21142             x00 = r0 * Math.cos(a00),
21143             y00 = r0 * Math.sin(a00);
21144
21145         // Restrict the corner radius according to the sector angle.
21146         if (da < pi$2) {
21147           var oc = da0 > epsilon$1 ? intersect(x01, y01, x00, y00, x11, y11, x10, y10) : [x10, y10],
21148               ax = x01 - oc[0],
21149               ay = y01 - oc[1],
21150               bx = x11 - oc[0],
21151               by = y11 - oc[1],
21152               kc = 1 / Math.sin(Math.acos((ax * bx + ay * by) / (Math.sqrt(ax * ax + ay * ay) * Math.sqrt(bx * bx + by * by))) / 2),
21153               lc = Math.sqrt(oc[0] * oc[0] + oc[1] * oc[1]);
21154           rc0 = Math.min(rc, (r0 - lc) / (kc - 1));
21155           rc1 = Math.min(rc, (r1 - lc) / (kc + 1));
21156         }
21157       }
21158
21159       // Is the sector collapsed to a line?
21160       if (!(da1 > epsilon$1)) context.moveTo(x01, y01);
21161
21162       // Does the sector’s outer ring have rounded corners?
21163       else if (rc1 > epsilon$1) {
21164         t0 = cornerTangents(x00, y00, x01, y01, r1, rc1, cw);
21165         t1 = cornerTangents(x11, y11, x10, y10, r1, rc1, cw);
21166
21167         context.moveTo(t0.cx + t0.x01, t0.cy + t0.y01);
21168
21169         // Have the corners merged?
21170         if (rc1 < rc) context.arc(t0.cx, t0.cy, rc1, Math.atan2(t0.y01, t0.x01), Math.atan2(t1.y01, t1.x01), !cw);
21171
21172         // Otherwise, draw the two corners and the ring.
21173         else {
21174           context.arc(t0.cx, t0.cy, rc1, Math.atan2(t0.y01, t0.x01), Math.atan2(t0.y11, t0.x11), !cw);
21175           context.arc(0, 0, r1, Math.atan2(t0.cy + t0.y11, t0.cx + t0.x11), Math.atan2(t1.cy + t1.y11, t1.cx + t1.x11), !cw);
21176           context.arc(t1.cx, t1.cy, rc1, Math.atan2(t1.y11, t1.x11), Math.atan2(t1.y01, t1.x01), !cw);
21177         }
21178       }
21179
21180       // Or is the outer ring just a circular arc?
21181       else context.moveTo(x01, y01), context.arc(0, 0, r1, a01, a11, !cw);
21182
21183       // Is there no inner ring, and it’s a circular sector?
21184       // Or perhaps it’s an annular sector collapsed due to padding?
21185       if (!(r0 > epsilon$1) || !(da0 > epsilon$1)) context.lineTo(x10, y10);
21186
21187       // Does the sector’s inner ring (or point) have rounded corners?
21188       else if (rc0 > epsilon$1) {
21189         t0 = cornerTangents(x10, y10, x11, y11, r0, -rc0, cw);
21190         t1 = cornerTangents(x01, y01, x00, y00, r0, -rc0, cw);
21191
21192         context.lineTo(t0.cx + t0.x01, t0.cy + t0.y01);
21193
21194         // Have the corners merged?
21195         if (rc0 < rc) context.arc(t0.cx, t0.cy, rc0, Math.atan2(t0.y01, t0.x01), Math.atan2(t1.y01, t1.x01), !cw);
21196
21197         // Otherwise, draw the two corners and the ring.
21198         else {
21199           context.arc(t0.cx, t0.cy, rc0, Math.atan2(t0.y01, t0.x01), Math.atan2(t0.y11, t0.x11), !cw);
21200           context.arc(0, 0, r0, Math.atan2(t0.cy + t0.y11, t0.cx + t0.x11), Math.atan2(t1.cy + t1.y11, t1.cx + t1.x11), cw);
21201           context.arc(t1.cx, t1.cy, rc0, Math.atan2(t1.y11, t1.x11), Math.atan2(t1.y01, t1.x01), !cw);
21202         }
21203       }
21204
21205       // Or is the inner ring just a circular arc?
21206       else context.arc(0, 0, r0, a10, a00, cw);
21207     }
21208
21209     context.closePath();
21210
21211     if (buffer) return context = null, buffer + "" || null;
21212   }
21213
21214   arc.centroid = function() {
21215     var r = (+innerRadius.apply(this, arguments) + +outerRadius.apply(this, arguments)) / 2,
21216         a = (+startAngle.apply(this, arguments) + +endAngle.apply(this, arguments)) / 2 - pi$2 / 2;
21217     return [Math.cos(a) * r, Math.sin(a) * r];
21218   };
21219
21220   arc.innerRadius = function(_) {
21221     return arguments.length ? (innerRadius = typeof _ === "function" ? _ : constant$2(+_), arc) : innerRadius;
21222   };
21223
21224   arc.outerRadius = function(_) {
21225     return arguments.length ? (outerRadius = typeof _ === "function" ? _ : constant$2(+_), arc) : outerRadius;
21226   };
21227
21228   arc.cornerRadius = function(_) {
21229     return arguments.length ? (cornerRadius = typeof _ === "function" ? _ : constant$2(+_), arc) : cornerRadius;
21230   };
21231
21232   arc.padRadius = function(_) {
21233     return arguments.length ? (padRadius = _ == null ? null : typeof _ === "function" ? _ : constant$2(+_), arc) : padRadius;
21234   };
21235
21236   arc.startAngle = function(_) {
21237     return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$2(+_), arc) : startAngle;
21238   };
21239
21240   arc.endAngle = function(_) {
21241     return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$2(+_), arc) : endAngle;
21242   };
21243
21244   arc.padAngle = function(_) {
21245     return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$2(+_), arc) : padAngle;
21246   };
21247
21248   arc.context = function(_) {
21249     return arguments.length ? ((context = _ == null ? null : _), arc) : context;
21250   };
21251
21252   return arc;
21253 };
21254
21255 function Linear(context) {
21256   this._context = context;
21257 }
21258
21259 Linear.prototype = {
21260   areaStart: function() {
21261     this._line = 0;
21262   },
21263   areaEnd: function() {
21264     this._line = NaN;
21265   },
21266   lineStart: function() {
21267     this._point = 0;
21268   },
21269   lineEnd: function() {
21270     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
21271     this._line = 1 - this._line;
21272   },
21273   point: function(x, y) {
21274     x = +x, y = +y;
21275     switch (this._point) {
21276       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
21277       case 1: this._point = 2; // proceed
21278       default: this._context.lineTo(x, y); break;
21279     }
21280   }
21281 };
21282
21283 var curveLinear = function(context) {
21284   return new Linear(context);
21285 };
21286
21287 function x(p) {
21288   return p[0];
21289 }
21290
21291 function y(p) {
21292   return p[1];
21293 }
21294
21295 var line = function() {
21296   var x$$1 = x,
21297       y$$1 = y,
21298       defined = constant$2(true),
21299       context = null,
21300       curve = curveLinear,
21301       output = null;
21302
21303   function line(data) {
21304     var i,
21305         n = data.length,
21306         d,
21307         defined0 = false,
21308         buffer;
21309
21310     if (context == null) output = curve(buffer = path());
21311
21312     for (i = 0; i <= n; ++i) {
21313       if (!(i < n && defined(d = data[i], i, data)) === defined0) {
21314         if (defined0 = !defined0) output.lineStart();
21315         else output.lineEnd();
21316       }
21317       if (defined0) output.point(+x$$1(d, i, data), +y$$1(d, i, data));
21318     }
21319
21320     if (buffer) return output = null, buffer + "" || null;
21321   }
21322
21323   line.x = function(_) {
21324     return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$2(+_), line) : x$$1;
21325   };
21326
21327   line.y = function(_) {
21328     return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$2(+_), line) : y$$1;
21329   };
21330
21331   line.defined = function(_) {
21332     return arguments.length ? (defined = typeof _ === "function" ? _ : constant$2(!!_), line) : defined;
21333   };
21334
21335   line.curve = function(_) {
21336     return arguments.length ? (curve = _, context != null && (output = curve(context)), line) : curve;
21337   };
21338
21339   line.context = function(_) {
21340     return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line) : context;
21341   };
21342
21343   return line;
21344 };
21345
21346 var area = function() {
21347   var x0 = x,
21348       x1 = null,
21349       y0 = constant$2(0),
21350       y1 = y,
21351       defined = constant$2(true),
21352       context = null,
21353       curve = curveLinear,
21354       output = null;
21355
21356   function area(data) {
21357     var i,
21358         j,
21359         k,
21360         n = data.length,
21361         d,
21362         defined0 = false,
21363         buffer,
21364         x0z = new Array(n),
21365         y0z = new Array(n);
21366
21367     if (context == null) output = curve(buffer = path());
21368
21369     for (i = 0; i <= n; ++i) {
21370       if (!(i < n && defined(d = data[i], i, data)) === defined0) {
21371         if (defined0 = !defined0) {
21372           j = i;
21373           output.areaStart();
21374           output.lineStart();
21375         } else {
21376           output.lineEnd();
21377           output.lineStart();
21378           for (k = i - 1; k >= j; --k) {
21379             output.point(x0z[k], y0z[k]);
21380           }
21381           output.lineEnd();
21382           output.areaEnd();
21383         }
21384       }
21385       if (defined0) {
21386         x0z[i] = +x0(d, i, data), y0z[i] = +y0(d, i, data);
21387         output.point(x1 ? +x1(d, i, data) : x0z[i], y1 ? +y1(d, i, data) : y0z[i]);
21388       }
21389     }
21390
21391     if (buffer) return output = null, buffer + "" || null;
21392   }
21393
21394   function arealine() {
21395     return line().defined(defined).curve(curve).context(context);
21396   }
21397
21398   area.x = function(_) {
21399     return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$2(+_), x1 = null, area) : x0;
21400   };
21401
21402   area.x0 = function(_) {
21403     return arguments.length ? (x0 = typeof _ === "function" ? _ : constant$2(+_), area) : x0;
21404   };
21405
21406   area.x1 = function(_) {
21407     return arguments.length ? (x1 = _ == null ? null : typeof _ === "function" ? _ : constant$2(+_), area) : x1;
21408   };
21409
21410   area.y = function(_) {
21411     return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$2(+_), y1 = null, area) : y0;
21412   };
21413
21414   area.y0 = function(_) {
21415     return arguments.length ? (y0 = typeof _ === "function" ? _ : constant$2(+_), area) : y0;
21416   };
21417
21418   area.y1 = function(_) {
21419     return arguments.length ? (y1 = _ == null ? null : typeof _ === "function" ? _ : constant$2(+_), area) : y1;
21420   };
21421
21422   area.lineX0 =
21423   area.lineY0 = function() {
21424     return arealine().x(x0).y(y0);
21425   };
21426
21427   area.lineY1 = function() {
21428     return arealine().x(x0).y(y1);
21429   };
21430
21431   area.lineX1 = function() {
21432     return arealine().x(x1).y(y0);
21433   };
21434
21435   area.defined = function(_) {
21436     return arguments.length ? (defined = typeof _ === "function" ? _ : constant$2(!!_), area) : defined;
21437   };
21438
21439   area.curve = function(_) {
21440     return arguments.length ? (curve = _, context != null && (output = curve(context)), area) : curve;
21441   };
21442
21443   area.context = function(_) {
21444     return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area) : context;
21445   };
21446
21447   return area;
21448 };
21449
21450 var descending$1 = function(a, b) {
21451   return b < a ? -1 : b > a ? 1 : b >= a ? 0 : NaN;
21452 };
21453
21454 var identity$1 = function(d) {
21455   return d;
21456 };
21457
21458 var pie = function() {
21459   var value = identity$1,
21460       sortValues = descending$1,
21461       sort = null,
21462       startAngle = constant$2(0),
21463       endAngle = constant$2(tau$2),
21464       padAngle = constant$2(0);
21465
21466   function pie(data) {
21467     var i,
21468         n = data.length,
21469         j,
21470         k,
21471         sum = 0,
21472         index = new Array(n),
21473         arcs = new Array(n),
21474         a0 = +startAngle.apply(this, arguments),
21475         da = Math.min(tau$2, Math.max(-tau$2, endAngle.apply(this, arguments) - a0)),
21476         a1,
21477         p = Math.min(Math.abs(da) / n, padAngle.apply(this, arguments)),
21478         pa = p * (da < 0 ? -1 : 1),
21479         v;
21480
21481     for (i = 0; i < n; ++i) {
21482       if ((v = arcs[index[i] = i] = +value(data[i], i, data)) > 0) {
21483         sum += v;
21484       }
21485     }
21486
21487     // Optionally sort the arcs by previously-computed values or by data.
21488     if (sortValues != null) index.sort(function(i, j) { return sortValues(arcs[i], arcs[j]); });
21489     else if (sort != null) index.sort(function(i, j) { return sort(data[i], data[j]); });
21490
21491     // Compute the arcs! They are stored in the original data's order.
21492     for (i = 0, k = sum ? (da - n * pa) / sum : 0; i < n; ++i, a0 = a1) {
21493       j = index[i], v = arcs[j], a1 = a0 + (v > 0 ? v * k : 0) + pa, arcs[j] = {
21494         data: data[j],
21495         index: i,
21496         value: v,
21497         startAngle: a0,
21498         endAngle: a1,
21499         padAngle: p
21500       };
21501     }
21502
21503     return arcs;
21504   }
21505
21506   pie.value = function(_) {
21507     return arguments.length ? (value = typeof _ === "function" ? _ : constant$2(+_), pie) : value;
21508   };
21509
21510   pie.sortValues = function(_) {
21511     return arguments.length ? (sortValues = _, sort = null, pie) : sortValues;
21512   };
21513
21514   pie.sort = function(_) {
21515     return arguments.length ? (sort = _, sortValues = null, pie) : sort;
21516   };
21517
21518   pie.startAngle = function(_) {
21519     return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$2(+_), pie) : startAngle;
21520   };
21521
21522   pie.endAngle = function(_) {
21523     return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$2(+_), pie) : endAngle;
21524   };
21525
21526   pie.padAngle = function(_) {
21527     return arguments.length ? (padAngle = typeof _ === "function" ? _ : constant$2(+_), pie) : padAngle;
21528   };
21529
21530   return pie;
21531 };
21532
21533 var curveRadialLinear = curveRadial(curveLinear);
21534
21535 function Radial(curve) {
21536   this._curve = curve;
21537 }
21538
21539 Radial.prototype = {
21540   areaStart: function() {
21541     this._curve.areaStart();
21542   },
21543   areaEnd: function() {
21544     this._curve.areaEnd();
21545   },
21546   lineStart: function() {
21547     this._curve.lineStart();
21548   },
21549   lineEnd: function() {
21550     this._curve.lineEnd();
21551   },
21552   point: function(a, r) {
21553     this._curve.point(r * Math.sin(a), r * -Math.cos(a));
21554   }
21555 };
21556
21557 function curveRadial(curve) {
21558
21559   function radial(context) {
21560     return new Radial(curve(context));
21561   }
21562
21563   radial._curve = curve;
21564
21565   return radial;
21566 }
21567
21568 function radialLine(l) {
21569   var c = l.curve;
21570
21571   l.angle = l.x, delete l.x;
21572   l.radius = l.y, delete l.y;
21573
21574   l.curve = function(_) {
21575     return arguments.length ? c(curveRadial(_)) : c()._curve;
21576   };
21577
21578   return l;
21579 }
21580
21581 var radialLine$1 = function() {
21582   return radialLine(line().curve(curveRadialLinear));
21583 };
21584
21585 var radialArea = function() {
21586   var a = area().curve(curveRadialLinear),
21587       c = a.curve,
21588       x0 = a.lineX0,
21589       x1 = a.lineX1,
21590       y0 = a.lineY0,
21591       y1 = a.lineY1;
21592
21593   a.angle = a.x, delete a.x;
21594   a.startAngle = a.x0, delete a.x0;
21595   a.endAngle = a.x1, delete a.x1;
21596   a.radius = a.y, delete a.y;
21597   a.innerRadius = a.y0, delete a.y0;
21598   a.outerRadius = a.y1, delete a.y1;
21599   a.lineStartAngle = function() { return radialLine(x0()); }, delete a.lineX0;
21600   a.lineEndAngle = function() { return radialLine(x1()); }, delete a.lineX1;
21601   a.lineInnerRadius = function() { return radialLine(y0()); }, delete a.lineY0;
21602   a.lineOuterRadius = function() { return radialLine(y1()); }, delete a.lineY1;
21603
21604   a.curve = function(_) {
21605     return arguments.length ? c(curveRadial(_)) : c()._curve;
21606   };
21607
21608   return a;
21609 };
21610
21611 var circle = {
21612   draw: function(context, size) {
21613     var r = Math.sqrt(size / pi$2);
21614     context.moveTo(r, 0);
21615     context.arc(0, 0, r, 0, tau$2);
21616   }
21617 };
21618
21619 var cross$1 = {
21620   draw: function(context, size) {
21621     var r = Math.sqrt(size / 5) / 2;
21622     context.moveTo(-3 * r, -r);
21623     context.lineTo(-r, -r);
21624     context.lineTo(-r, -3 * r);
21625     context.lineTo(r, -3 * r);
21626     context.lineTo(r, -r);
21627     context.lineTo(3 * r, -r);
21628     context.lineTo(3 * r, r);
21629     context.lineTo(r, r);
21630     context.lineTo(r, 3 * r);
21631     context.lineTo(-r, 3 * r);
21632     context.lineTo(-r, r);
21633     context.lineTo(-3 * r, r);
21634     context.closePath();
21635   }
21636 };
21637
21638 var tan30 = Math.sqrt(1 / 3);
21639 var tan30_2 = tan30 * 2;
21640
21641 var diamond = {
21642   draw: function(context, size) {
21643     var y = Math.sqrt(size / tan30_2),
21644         x = y * tan30;
21645     context.moveTo(0, -y);
21646     context.lineTo(x, 0);
21647     context.lineTo(0, y);
21648     context.lineTo(-x, 0);
21649     context.closePath();
21650   }
21651 };
21652
21653 var ka = 0.89081309152928522810;
21654 var kr = Math.sin(pi$2 / 10) / Math.sin(7 * pi$2 / 10);
21655 var kx = Math.sin(tau$2 / 10) * kr;
21656 var ky = -Math.cos(tau$2 / 10) * kr;
21657
21658 var star = {
21659   draw: function(context, size) {
21660     var r = Math.sqrt(size * ka),
21661         x = kx * r,
21662         y = ky * r;
21663     context.moveTo(0, -r);
21664     context.lineTo(x, y);
21665     for (var i = 1; i < 5; ++i) {
21666       var a = tau$2 * i / 5,
21667           c = Math.cos(a),
21668           s = Math.sin(a);
21669       context.lineTo(s * r, -c * r);
21670       context.lineTo(c * x - s * y, s * x + c * y);
21671     }
21672     context.closePath();
21673   }
21674 };
21675
21676 var square = {
21677   draw: function(context, size) {
21678     var w = Math.sqrt(size),
21679         x = -w / 2;
21680     context.rect(x, x, w, w);
21681   }
21682 };
21683
21684 var sqrt3 = Math.sqrt(3);
21685
21686 var triangle = {
21687   draw: function(context, size) {
21688     var y = -Math.sqrt(size / (sqrt3 * 3));
21689     context.moveTo(0, y * 2);
21690     context.lineTo(-sqrt3 * y, -y);
21691     context.lineTo(sqrt3 * y, -y);
21692     context.closePath();
21693   }
21694 };
21695
21696 var c = -0.5;
21697 var s = Math.sqrt(3) / 2;
21698 var k = 1 / Math.sqrt(12);
21699 var a = (k / 2 + 1) * 3;
21700
21701 var wye = {
21702   draw: function(context, size) {
21703     var r = Math.sqrt(size / a),
21704         x0 = r / 2,
21705         y0 = r * k,
21706         x1 = x0,
21707         y1 = r * k + r,
21708         x2 = -x1,
21709         y2 = y1;
21710     context.moveTo(x0, y0);
21711     context.lineTo(x1, y1);
21712     context.lineTo(x2, y2);
21713     context.lineTo(c * x0 - s * y0, s * x0 + c * y0);
21714     context.lineTo(c * x1 - s * y1, s * x1 + c * y1);
21715     context.lineTo(c * x2 - s * y2, s * x2 + c * y2);
21716     context.lineTo(c * x0 + s * y0, c * y0 - s * x0);
21717     context.lineTo(c * x1 + s * y1, c * y1 - s * x1);
21718     context.lineTo(c * x2 + s * y2, c * y2 - s * x2);
21719     context.closePath();
21720   }
21721 };
21722
21723 var symbols = [
21724   circle,
21725   cross$1,
21726   diamond,
21727   square,
21728   star,
21729   triangle,
21730   wye
21731 ];
21732
21733 var symbol = function() {
21734   var type = constant$2(circle),
21735       size = constant$2(64),
21736       context = null;
21737
21738   function symbol() {
21739     var buffer;
21740     if (!context) context = buffer = path();
21741     type.apply(this, arguments).draw(context, +size.apply(this, arguments));
21742     if (buffer) return context = null, buffer + "" || null;
21743   }
21744
21745   symbol.type = function(_) {
21746     return arguments.length ? (type = typeof _ === "function" ? _ : constant$2(_), symbol) : type;
21747   };
21748
21749   symbol.size = function(_) {
21750     return arguments.length ? (size = typeof _ === "function" ? _ : constant$2(+_), symbol) : size;
21751   };
21752
21753   symbol.context = function(_) {
21754     return arguments.length ? (context = _ == null ? null : _, symbol) : context;
21755   };
21756
21757   return symbol;
21758 };
21759
21760 var noop = function() {};
21761
21762 function point(that, x, y) {
21763   that._context.bezierCurveTo(
21764     (2 * that._x0 + that._x1) / 3,
21765     (2 * that._y0 + that._y1) / 3,
21766     (that._x0 + 2 * that._x1) / 3,
21767     (that._y0 + 2 * that._y1) / 3,
21768     (that._x0 + 4 * that._x1 + x) / 6,
21769     (that._y0 + 4 * that._y1 + y) / 6
21770   );
21771 }
21772
21773 function Basis(context) {
21774   this._context = context;
21775 }
21776
21777 Basis.prototype = {
21778   areaStart: function() {
21779     this._line = 0;
21780   },
21781   areaEnd: function() {
21782     this._line = NaN;
21783   },
21784   lineStart: function() {
21785     this._x0 = this._x1 =
21786     this._y0 = this._y1 = NaN;
21787     this._point = 0;
21788   },
21789   lineEnd: function() {
21790     switch (this._point) {
21791       case 3: point(this, this._x1, this._y1); // proceed
21792       case 2: this._context.lineTo(this._x1, this._y1); break;
21793     }
21794     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
21795     this._line = 1 - this._line;
21796   },
21797   point: function(x, y) {
21798     x = +x, y = +y;
21799     switch (this._point) {
21800       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
21801       case 1: this._point = 2; break;
21802       case 2: this._point = 3; this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6); // proceed
21803       default: point(this, x, y); break;
21804     }
21805     this._x0 = this._x1, this._x1 = x;
21806     this._y0 = this._y1, this._y1 = y;
21807   }
21808 };
21809
21810 var basis = function(context) {
21811   return new Basis(context);
21812 };
21813
21814 function BasisClosed(context) {
21815   this._context = context;
21816 }
21817
21818 BasisClosed.prototype = {
21819   areaStart: noop,
21820   areaEnd: noop,
21821   lineStart: function() {
21822     this._x0 = this._x1 = this._x2 = this._x3 = this._x4 =
21823     this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN;
21824     this._point = 0;
21825   },
21826   lineEnd: function() {
21827     switch (this._point) {
21828       case 1: {
21829         this._context.moveTo(this._x2, this._y2);
21830         this._context.closePath();
21831         break;
21832       }
21833       case 2: {
21834         this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3);
21835         this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3);
21836         this._context.closePath();
21837         break;
21838       }
21839       case 3: {
21840         this.point(this._x2, this._y2);
21841         this.point(this._x3, this._y3);
21842         this.point(this._x4, this._y4);
21843         break;
21844       }
21845     }
21846   },
21847   point: function(x, y) {
21848     x = +x, y = +y;
21849     switch (this._point) {
21850       case 0: this._point = 1; this._x2 = x, this._y2 = y; break;
21851       case 1: this._point = 2; this._x3 = x, this._y3 = y; break;
21852       case 2: this._point = 3; this._x4 = x, this._y4 = y; this._context.moveTo((this._x0 + 4 * this._x1 + x) / 6, (this._y0 + 4 * this._y1 + y) / 6); break;
21853       default: point(this, x, y); break;
21854     }
21855     this._x0 = this._x1, this._x1 = x;
21856     this._y0 = this._y1, this._y1 = y;
21857   }
21858 };
21859
21860 var basisClosed = function(context) {
21861   return new BasisClosed(context);
21862 };
21863
21864 function BasisOpen(context) {
21865   this._context = context;
21866 }
21867
21868 BasisOpen.prototype = {
21869   areaStart: function() {
21870     this._line = 0;
21871   },
21872   areaEnd: function() {
21873     this._line = NaN;
21874   },
21875   lineStart: function() {
21876     this._x0 = this._x1 =
21877     this._y0 = this._y1 = NaN;
21878     this._point = 0;
21879   },
21880   lineEnd: function() {
21881     if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
21882     this._line = 1 - this._line;
21883   },
21884   point: function(x, y) {
21885     x = +x, y = +y;
21886     switch (this._point) {
21887       case 0: this._point = 1; break;
21888       case 1: this._point = 2; break;
21889       case 2: this._point = 3; var x0 = (this._x0 + 4 * this._x1 + x) / 6, y0 = (this._y0 + 4 * this._y1 + y) / 6; this._line ? this._context.lineTo(x0, y0) : this._context.moveTo(x0, y0); break;
21890       case 3: this._point = 4; // proceed
21891       default: point(this, x, y); break;
21892     }
21893     this._x0 = this._x1, this._x1 = x;
21894     this._y0 = this._y1, this._y1 = y;
21895   }
21896 };
21897
21898 var basisOpen = function(context) {
21899   return new BasisOpen(context);
21900 };
21901
21902 function Bundle(context, beta) {
21903   this._basis = new Basis(context);
21904   this._beta = beta;
21905 }
21906
21907 Bundle.prototype = {
21908   lineStart: function() {
21909     this._x = [];
21910     this._y = [];
21911     this._basis.lineStart();
21912   },
21913   lineEnd: function() {
21914     var x = this._x,
21915         y = this._y,
21916         j = x.length - 1;
21917
21918     if (j > 0) {
21919       var x0 = x[0],
21920           y0 = y[0],
21921           dx = x[j] - x0,
21922           dy = y[j] - y0,
21923           i = -1,
21924           t;
21925
21926       while (++i <= j) {
21927         t = i / j;
21928         this._basis.point(
21929           this._beta * x[i] + (1 - this._beta) * (x0 + t * dx),
21930           this._beta * y[i] + (1 - this._beta) * (y0 + t * dy)
21931         );
21932       }
21933     }
21934
21935     this._x = this._y = null;
21936     this._basis.lineEnd();
21937   },
21938   point: function(x, y) {
21939     this._x.push(+x);
21940     this._y.push(+y);
21941   }
21942 };
21943
21944 var bundle = (function custom(beta) {
21945
21946   function bundle(context) {
21947     return beta === 1 ? new Basis(context) : new Bundle(context, beta);
21948   }
21949
21950   bundle.beta = function(beta) {
21951     return custom(+beta);
21952   };
21953
21954   return bundle;
21955 })(0.85);
21956
21957 function point$1(that, x, y) {
21958   that._context.bezierCurveTo(
21959     that._x1 + that._k * (that._x2 - that._x0),
21960     that._y1 + that._k * (that._y2 - that._y0),
21961     that._x2 + that._k * (that._x1 - x),
21962     that._y2 + that._k * (that._y1 - y),
21963     that._x2,
21964     that._y2
21965   );
21966 }
21967
21968 function Cardinal(context, tension) {
21969   this._context = context;
21970   this._k = (1 - tension) / 6;
21971 }
21972
21973 Cardinal.prototype = {
21974   areaStart: function() {
21975     this._line = 0;
21976   },
21977   areaEnd: function() {
21978     this._line = NaN;
21979   },
21980   lineStart: function() {
21981     this._x0 = this._x1 = this._x2 =
21982     this._y0 = this._y1 = this._y2 = NaN;
21983     this._point = 0;
21984   },
21985   lineEnd: function() {
21986     switch (this._point) {
21987       case 2: this._context.lineTo(this._x2, this._y2); break;
21988       case 3: point$1(this, this._x1, this._y1); break;
21989     }
21990     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
21991     this._line = 1 - this._line;
21992   },
21993   point: function(x, y) {
21994     x = +x, y = +y;
21995     switch (this._point) {
21996       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
21997       case 1: this._point = 2; this._x1 = x, this._y1 = y; break;
21998       case 2: this._point = 3; // proceed
21999       default: point$1(this, x, y); break;
22000     }
22001     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
22002     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
22003   }
22004 };
22005
22006 var cardinal = (function custom(tension) {
22007
22008   function cardinal(context) {
22009     return new Cardinal(context, tension);
22010   }
22011
22012   cardinal.tension = function(tension) {
22013     return custom(+tension);
22014   };
22015
22016   return cardinal;
22017 })(0);
22018
22019 function CardinalClosed(context, tension) {
22020   this._context = context;
22021   this._k = (1 - tension) / 6;
22022 }
22023
22024 CardinalClosed.prototype = {
22025   areaStart: noop,
22026   areaEnd: noop,
22027   lineStart: function() {
22028     this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 =
22029     this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;
22030     this._point = 0;
22031   },
22032   lineEnd: function() {
22033     switch (this._point) {
22034       case 1: {
22035         this._context.moveTo(this._x3, this._y3);
22036         this._context.closePath();
22037         break;
22038       }
22039       case 2: {
22040         this._context.lineTo(this._x3, this._y3);
22041         this._context.closePath();
22042         break;
22043       }
22044       case 3: {
22045         this.point(this._x3, this._y3);
22046         this.point(this._x4, this._y4);
22047         this.point(this._x5, this._y5);
22048         break;
22049       }
22050     }
22051   },
22052   point: function(x, y) {
22053     x = +x, y = +y;
22054     switch (this._point) {
22055       case 0: this._point = 1; this._x3 = x, this._y3 = y; break;
22056       case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break;
22057       case 2: this._point = 3; this._x5 = x, this._y5 = y; break;
22058       default: point$1(this, x, y); break;
22059     }
22060     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
22061     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
22062   }
22063 };
22064
22065 var cardinalClosed = (function custom(tension) {
22066
22067   function cardinal(context) {
22068     return new CardinalClosed(context, tension);
22069   }
22070
22071   cardinal.tension = function(tension) {
22072     return custom(+tension);
22073   };
22074
22075   return cardinal;
22076 })(0);
22077
22078 function CardinalOpen(context, tension) {
22079   this._context = context;
22080   this._k = (1 - tension) / 6;
22081 }
22082
22083 CardinalOpen.prototype = {
22084   areaStart: function() {
22085     this._line = 0;
22086   },
22087   areaEnd: function() {
22088     this._line = NaN;
22089   },
22090   lineStart: function() {
22091     this._x0 = this._x1 = this._x2 =
22092     this._y0 = this._y1 = this._y2 = NaN;
22093     this._point = 0;
22094   },
22095   lineEnd: function() {
22096     if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
22097     this._line = 1 - this._line;
22098   },
22099   point: function(x, y) {
22100     x = +x, y = +y;
22101     switch (this._point) {
22102       case 0: this._point = 1; break;
22103       case 1: this._point = 2; break;
22104       case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break;
22105       case 3: this._point = 4; // proceed
22106       default: point$1(this, x, y); break;
22107     }
22108     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
22109     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
22110   }
22111 };
22112
22113 var cardinalOpen = (function custom(tension) {
22114
22115   function cardinal(context) {
22116     return new CardinalOpen(context, tension);
22117   }
22118
22119   cardinal.tension = function(tension) {
22120     return custom(+tension);
22121   };
22122
22123   return cardinal;
22124 })(0);
22125
22126 function point$2(that, x, y) {
22127   var x1 = that._x1,
22128       y1 = that._y1,
22129       x2 = that._x2,
22130       y2 = that._y2;
22131
22132   if (that._l01_a > epsilon$1) {
22133     var a = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a,
22134         n = 3 * that._l01_a * (that._l01_a + that._l12_a);
22135     x1 = (x1 * a - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n;
22136     y1 = (y1 * a - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n;
22137   }
22138
22139   if (that._l23_a > epsilon$1) {
22140     var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a,
22141         m = 3 * that._l23_a * (that._l23_a + that._l12_a);
22142     x2 = (x2 * b + that._x1 * that._l23_2a - x * that._l12_2a) / m;
22143     y2 = (y2 * b + that._y1 * that._l23_2a - y * that._l12_2a) / m;
22144   }
22145
22146   that._context.bezierCurveTo(x1, y1, x2, y2, that._x2, that._y2);
22147 }
22148
22149 function CatmullRom(context, alpha) {
22150   this._context = context;
22151   this._alpha = alpha;
22152 }
22153
22154 CatmullRom.prototype = {
22155   areaStart: function() {
22156     this._line = 0;
22157   },
22158   areaEnd: function() {
22159     this._line = NaN;
22160   },
22161   lineStart: function() {
22162     this._x0 = this._x1 = this._x2 =
22163     this._y0 = this._y1 = this._y2 = NaN;
22164     this._l01_a = this._l12_a = this._l23_a =
22165     this._l01_2a = this._l12_2a = this._l23_2a =
22166     this._point = 0;
22167   },
22168   lineEnd: function() {
22169     switch (this._point) {
22170       case 2: this._context.lineTo(this._x2, this._y2); break;
22171       case 3: this.point(this._x2, this._y2); break;
22172     }
22173     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
22174     this._line = 1 - this._line;
22175   },
22176   point: function(x, y) {
22177     x = +x, y = +y;
22178
22179     if (this._point) {
22180       var x23 = this._x2 - x,
22181           y23 = this._y2 - y;
22182       this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
22183     }
22184
22185     switch (this._point) {
22186       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
22187       case 1: this._point = 2; break;
22188       case 2: this._point = 3; // proceed
22189       default: point$2(this, x, y); break;
22190     }
22191
22192     this._l01_a = this._l12_a, this._l12_a = this._l23_a;
22193     this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
22194     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
22195     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
22196   }
22197 };
22198
22199 var catmullRom = (function custom(alpha) {
22200
22201   function catmullRom(context) {
22202     return alpha ? new CatmullRom(context, alpha) : new Cardinal(context, 0);
22203   }
22204
22205   catmullRom.alpha = function(alpha) {
22206     return custom(+alpha);
22207   };
22208
22209   return catmullRom;
22210 })(0.5);
22211
22212 function CatmullRomClosed(context, alpha) {
22213   this._context = context;
22214   this._alpha = alpha;
22215 }
22216
22217 CatmullRomClosed.prototype = {
22218   areaStart: noop,
22219   areaEnd: noop,
22220   lineStart: function() {
22221     this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 =
22222     this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;
22223     this._l01_a = this._l12_a = this._l23_a =
22224     this._l01_2a = this._l12_2a = this._l23_2a =
22225     this._point = 0;
22226   },
22227   lineEnd: function() {
22228     switch (this._point) {
22229       case 1: {
22230         this._context.moveTo(this._x3, this._y3);
22231         this._context.closePath();
22232         break;
22233       }
22234       case 2: {
22235         this._context.lineTo(this._x3, this._y3);
22236         this._context.closePath();
22237         break;
22238       }
22239       case 3: {
22240         this.point(this._x3, this._y3);
22241         this.point(this._x4, this._y4);
22242         this.point(this._x5, this._y5);
22243         break;
22244       }
22245     }
22246   },
22247   point: function(x, y) {
22248     x = +x, y = +y;
22249
22250     if (this._point) {
22251       var x23 = this._x2 - x,
22252           y23 = this._y2 - y;
22253       this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
22254     }
22255
22256     switch (this._point) {
22257       case 0: this._point = 1; this._x3 = x, this._y3 = y; break;
22258       case 1: this._point = 2; this._context.moveTo(this._x4 = x, this._y4 = y); break;
22259       case 2: this._point = 3; this._x5 = x, this._y5 = y; break;
22260       default: point$2(this, x, y); break;
22261     }
22262
22263     this._l01_a = this._l12_a, this._l12_a = this._l23_a;
22264     this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
22265     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
22266     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
22267   }
22268 };
22269
22270 var catmullRomClosed = (function custom(alpha) {
22271
22272   function catmullRom(context) {
22273     return alpha ? new CatmullRomClosed(context, alpha) : new CardinalClosed(context, 0);
22274   }
22275
22276   catmullRom.alpha = function(alpha) {
22277     return custom(+alpha);
22278   };
22279
22280   return catmullRom;
22281 })(0.5);
22282
22283 function CatmullRomOpen(context, alpha) {
22284   this._context = context;
22285   this._alpha = alpha;
22286 }
22287
22288 CatmullRomOpen.prototype = {
22289   areaStart: function() {
22290     this._line = 0;
22291   },
22292   areaEnd: function() {
22293     this._line = NaN;
22294   },
22295   lineStart: function() {
22296     this._x0 = this._x1 = this._x2 =
22297     this._y0 = this._y1 = this._y2 = NaN;
22298     this._l01_a = this._l12_a = this._l23_a =
22299     this._l01_2a = this._l12_2a = this._l23_2a =
22300     this._point = 0;
22301   },
22302   lineEnd: function() {
22303     if (this._line || (this._line !== 0 && this._point === 3)) this._context.closePath();
22304     this._line = 1 - this._line;
22305   },
22306   point: function(x, y) {
22307     x = +x, y = +y;
22308
22309     if (this._point) {
22310       var x23 = this._x2 - x,
22311           y23 = this._y2 - y;
22312       this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));
22313     }
22314
22315     switch (this._point) {
22316       case 0: this._point = 1; break;
22317       case 1: this._point = 2; break;
22318       case 2: this._point = 3; this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2); break;
22319       case 3: this._point = 4; // proceed
22320       default: point$2(this, x, y); break;
22321     }
22322
22323     this._l01_a = this._l12_a, this._l12_a = this._l23_a;
22324     this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;
22325     this._x0 = this._x1, this._x1 = this._x2, this._x2 = x;
22326     this._y0 = this._y1, this._y1 = this._y2, this._y2 = y;
22327   }
22328 };
22329
22330 var catmullRomOpen = (function custom(alpha) {
22331
22332   function catmullRom(context) {
22333     return alpha ? new CatmullRomOpen(context, alpha) : new CardinalOpen(context, 0);
22334   }
22335
22336   catmullRom.alpha = function(alpha) {
22337     return custom(+alpha);
22338   };
22339
22340   return catmullRom;
22341 })(0.5);
22342
22343 function LinearClosed(context) {
22344   this._context = context;
22345 }
22346
22347 LinearClosed.prototype = {
22348   areaStart: noop,
22349   areaEnd: noop,
22350   lineStart: function() {
22351     this._point = 0;
22352   },
22353   lineEnd: function() {
22354     if (this._point) this._context.closePath();
22355   },
22356   point: function(x, y) {
22357     x = +x, y = +y;
22358     if (this._point) this._context.lineTo(x, y);
22359     else this._point = 1, this._context.moveTo(x, y);
22360   }
22361 };
22362
22363 var linearClosed = function(context) {
22364   return new LinearClosed(context);
22365 };
22366
22367 function sign(x) {
22368   return x < 0 ? -1 : 1;
22369 }
22370
22371 // Calculate the slopes of the tangents (Hermite-type interpolation) based on
22372 // the following paper: Steffen, M. 1990. A Simple Method for Monotonic
22373 // Interpolation in One Dimension. Astronomy and Astrophysics, Vol. 239, NO.
22374 // NOV(II), P. 443, 1990.
22375 function slope3(that, x2, y2) {
22376   var h0 = that._x1 - that._x0,
22377       h1 = x2 - that._x1,
22378       s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0),
22379       s1 = (y2 - that._y1) / (h1 || h0 < 0 && -0),
22380       p = (s0 * h1 + s1 * h0) / (h0 + h1);
22381   return (sign(s0) + sign(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0;
22382 }
22383
22384 // Calculate a one-sided slope.
22385 function slope2(that, t) {
22386   var h = that._x1 - that._x0;
22387   return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t;
22388 }
22389
22390 // According to https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Representations
22391 // "you can express cubic Hermite interpolation in terms of cubic Bézier curves
22392 // with respect to the four values p0, p0 + m0 / 3, p1 - m1 / 3, p1".
22393 function point$3(that, t0, t1) {
22394   var x0 = that._x0,
22395       y0 = that._y0,
22396       x1 = that._x1,
22397       y1 = that._y1,
22398       dx = (x1 - x0) / 3;
22399   that._context.bezierCurveTo(x0 + dx, y0 + dx * t0, x1 - dx, y1 - dx * t1, x1, y1);
22400 }
22401
22402 function MonotoneX(context) {
22403   this._context = context;
22404 }
22405
22406 MonotoneX.prototype = {
22407   areaStart: function() {
22408     this._line = 0;
22409   },
22410   areaEnd: function() {
22411     this._line = NaN;
22412   },
22413   lineStart: function() {
22414     this._x0 = this._x1 =
22415     this._y0 = this._y1 =
22416     this._t0 = NaN;
22417     this._point = 0;
22418   },
22419   lineEnd: function() {
22420     switch (this._point) {
22421       case 2: this._context.lineTo(this._x1, this._y1); break;
22422       case 3: point$3(this, this._t0, slope2(this, this._t0)); break;
22423     }
22424     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
22425     this._line = 1 - this._line;
22426   },
22427   point: function(x, y) {
22428     var t1 = NaN;
22429
22430     x = +x, y = +y;
22431     if (x === this._x1 && y === this._y1) return; // Ignore coincident points.
22432     switch (this._point) {
22433       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
22434       case 1: this._point = 2; break;
22435       case 2: this._point = 3; point$3(this, slope2(this, t1 = slope3(this, x, y)), t1); break;
22436       default: point$3(this, this._t0, t1 = slope3(this, x, y)); break;
22437     }
22438
22439     this._x0 = this._x1, this._x1 = x;
22440     this._y0 = this._y1, this._y1 = y;
22441     this._t0 = t1;
22442   }
22443 };
22444
22445 function MonotoneY(context) {
22446   this._context = new ReflectContext(context);
22447 }
22448
22449 (MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(x, y) {
22450   MonotoneX.prototype.point.call(this, y, x);
22451 };
22452
22453 function ReflectContext(context) {
22454   this._context = context;
22455 }
22456
22457 ReflectContext.prototype = {
22458   moveTo: function(x, y) { this._context.moveTo(y, x); },
22459   closePath: function() { this._context.closePath(); },
22460   lineTo: function(x, y) { this._context.lineTo(y, x); },
22461   bezierCurveTo: function(x1, y1, x2, y2, x, y) { this._context.bezierCurveTo(y1, x1, y2, x2, y, x); }
22462 };
22463
22464 function monotoneX(context) {
22465   return new MonotoneX(context);
22466 }
22467
22468 function monotoneY(context) {
22469   return new MonotoneY(context);
22470 }
22471
22472 function Natural(context) {
22473   this._context = context;
22474 }
22475
22476 Natural.prototype = {
22477   areaStart: function() {
22478     this._line = 0;
22479   },
22480   areaEnd: function() {
22481     this._line = NaN;
22482   },
22483   lineStart: function() {
22484     this._x = [];
22485     this._y = [];
22486   },
22487   lineEnd: function() {
22488     var x = this._x,
22489         y = this._y,
22490         n = x.length;
22491
22492     if (n) {
22493       this._line ? this._context.lineTo(x[0], y[0]) : this._context.moveTo(x[0], y[0]);
22494       if (n === 2) {
22495         this._context.lineTo(x[1], y[1]);
22496       } else {
22497         var px = controlPoints(x),
22498             py = controlPoints(y);
22499         for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) {
22500           this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x[i1], y[i1]);
22501         }
22502       }
22503     }
22504
22505     if (this._line || (this._line !== 0 && n === 1)) this._context.closePath();
22506     this._line = 1 - this._line;
22507     this._x = this._y = null;
22508   },
22509   point: function(x, y) {
22510     this._x.push(+x);
22511     this._y.push(+y);
22512   }
22513 };
22514
22515 // See https://www.particleincell.com/2012/bezier-splines/ for derivation.
22516 function controlPoints(x) {
22517   var i,
22518       n = x.length - 1,
22519       m,
22520       a = new Array(n),
22521       b = new Array(n),
22522       r = new Array(n);
22523   a[0] = 0, b[0] = 2, r[0] = x[0] + 2 * x[1];
22524   for (i = 1; i < n - 1; ++i) a[i] = 1, b[i] = 4, r[i] = 4 * x[i] + 2 * x[i + 1];
22525   a[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x[n - 1] + x[n];
22526   for (i = 1; i < n; ++i) m = a[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1];
22527   a[n - 1] = r[n - 1] / b[n - 1];
22528   for (i = n - 2; i >= 0; --i) a[i] = (r[i] - a[i + 1]) / b[i];
22529   b[n - 1] = (x[n] + a[n - 1]) / 2;
22530   for (i = 0; i < n - 1; ++i) b[i] = 2 * x[i + 1] - a[i + 1];
22531   return [a, b];
22532 }
22533
22534 var natural = function(context) {
22535   return new Natural(context);
22536 };
22537
22538 function Step(context, t) {
22539   this._context = context;
22540   this._t = t;
22541 }
22542
22543 Step.prototype = {
22544   areaStart: function() {
22545     this._line = 0;
22546   },
22547   areaEnd: function() {
22548     this._line = NaN;
22549   },
22550   lineStart: function() {
22551     this._x = this._y = NaN;
22552     this._point = 0;
22553   },
22554   lineEnd: function() {
22555     if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y);
22556     if (this._line || (this._line !== 0 && this._point === 1)) this._context.closePath();
22557     if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line;
22558   },
22559   point: function(x, y) {
22560     x = +x, y = +y;
22561     switch (this._point) {
22562       case 0: this._point = 1; this._line ? this._context.lineTo(x, y) : this._context.moveTo(x, y); break;
22563       case 1: this._point = 2; // proceed
22564       default: {
22565         if (this._t <= 0) {
22566           this._context.lineTo(this._x, y);
22567           this._context.lineTo(x, y);
22568         } else {
22569           var x1 = this._x * (1 - this._t) + x * this._t;
22570           this._context.lineTo(x1, this._y);
22571           this._context.lineTo(x1, y);
22572         }
22573         break;
22574       }
22575     }
22576     this._x = x, this._y = y;
22577   }
22578 };
22579
22580 var step = function(context) {
22581   return new Step(context, 0.5);
22582 };
22583
22584 function stepBefore(context) {
22585   return new Step(context, 0);
22586 }
22587
22588 function stepAfter(context) {
22589   return new Step(context, 1);
22590 }
22591
22592 var slice$2 = Array.prototype.slice;
22593
22594 var none = function(series, order) {
22595   if (!((n = series.length) > 1)) return;
22596   for (var i = 1, s0, s1 = series[order[0]], n, m = s1.length; i < n; ++i) {
22597     s0 = s1, s1 = series[order[i]];
22598     for (var j = 0; j < m; ++j) {
22599       s1[j][1] += s1[j][0] = isNaN(s0[j][1]) ? s0[j][0] : s0[j][1];
22600     }
22601   }
22602 };
22603
22604 var none$1 = function(series) {
22605   var n = series.length, o = new Array(n);
22606   while (--n >= 0) o[n] = n;
22607   return o;
22608 };
22609
22610 function stackValue(d, key) {
22611   return d[key];
22612 }
22613
22614 var stack = function() {
22615   var keys = constant$2([]),
22616       order = none$1,
22617       offset = none,
22618       value = stackValue;
22619
22620   function stack(data) {
22621     var kz = keys.apply(this, arguments),
22622         i,
22623         m = data.length,
22624         n = kz.length,
22625         sz = new Array(n),
22626         oz;
22627
22628     for (i = 0; i < n; ++i) {
22629       for (var ki = kz[i], si = sz[i] = new Array(m), j = 0, sij; j < m; ++j) {
22630         si[j] = sij = [0, +value(data[j], ki, j, data)];
22631         sij.data = data[j];
22632       }
22633       si.key = ki;
22634     }
22635
22636     for (i = 0, oz = order(sz); i < n; ++i) {
22637       sz[oz[i]].index = i;
22638     }
22639
22640     offset(sz, oz);
22641     return sz;
22642   }
22643
22644   stack.keys = function(_) {
22645     return arguments.length ? (keys = typeof _ === "function" ? _ : constant$2(slice$2.call(_)), stack) : keys;
22646   };
22647
22648   stack.value = function(_) {
22649     return arguments.length ? (value = typeof _ === "function" ? _ : constant$2(+_), stack) : value;
22650   };
22651
22652   stack.order = function(_) {
22653     return arguments.length ? (order = _ == null ? none$1 : typeof _ === "function" ? _ : constant$2(slice$2.call(_)), stack) : order;
22654   };
22655
22656   stack.offset = function(_) {
22657     return arguments.length ? (offset = _ == null ? none : _, stack) : offset;
22658   };
22659
22660   return stack;
22661 };
22662
22663 var expand = function(series, order) {
22664   if (!((n = series.length) > 0)) return;
22665   for (var i, n, j = 0, m = series[0].length, y; j < m; ++j) {
22666     for (y = i = 0; i < n; ++i) y += series[i][j][1] || 0;
22667     if (y) for (i = 0; i < n; ++i) series[i][j][1] /= y;
22668   }
22669   none(series, order);
22670 };
22671
22672 var silhouette = function(series, order) {
22673   if (!((n = series.length) > 0)) return;
22674   for (var j = 0, s0 = series[order[0]], n, m = s0.length; j < m; ++j) {
22675     for (var i = 0, y = 0; i < n; ++i) y += series[i][j][1] || 0;
22676     s0[j][1] += s0[j][0] = -y / 2;
22677   }
22678   none(series, order);
22679 };
22680
22681 var wiggle = function(series, order) {
22682   if (!((n = series.length) > 0) || !((m = (s0 = series[order[0]]).length) > 0)) return;
22683   for (var y = 0, j = 1, s0, m, n; j < m; ++j) {
22684     for (var i = 0, s1 = 0, s2 = 0; i < n; ++i) {
22685       var si = series[order[i]],
22686           sij0 = si[j][1] || 0,
22687           sij1 = si[j - 1][1] || 0,
22688           s3 = (sij0 - sij1) / 2;
22689       for (var k = 0; k < i; ++k) {
22690         var sk = series[order[k]],
22691             skj0 = sk[j][1] || 0,
22692             skj1 = sk[j - 1][1] || 0;
22693         s3 += skj0 - skj1;
22694       }
22695       s1 += sij0, s2 += s3 * sij0;
22696     }
22697     s0[j - 1][1] += s0[j - 1][0] = y;
22698     if (s1) y -= s2 / s1;
22699   }
22700   s0[j - 1][1] += s0[j - 1][0] = y;
22701   none(series, order);
22702 };
22703
22704 var ascending$1 = function(series) {
22705   var sums = series.map(sum$1);
22706   return none$1(series).sort(function(a, b) { return sums[a] - sums[b]; });
22707 };
22708
22709 function sum$1(series) {
22710   var s = 0, i = -1, n = series.length, v;
22711   while (++i < n) if (v = +series[i][1]) s += v;
22712   return s;
22713 }
22714
22715 var descending$2 = function(series) {
22716   return ascending$1(series).reverse();
22717 };
22718
22719 var insideOut = function(series) {
22720   var n = series.length,
22721       i,
22722       j,
22723       sums = series.map(sum$1),
22724       order = none$1(series).sort(function(a, b) { return sums[b] - sums[a]; }),
22725       top = 0,
22726       bottom = 0,
22727       tops = [],
22728       bottoms = [];
22729
22730   for (i = 0; i < n; ++i) {
22731     j = order[i];
22732     if (top < bottom) {
22733       top += sums[j];
22734       tops.push(j);
22735     } else {
22736       bottom += sums[j];
22737       bottoms.push(j);
22738     }
22739   }
22740
22741   return bottoms.reverse().concat(tops);
22742 };
22743
22744 var reverse = function(series) {
22745   return none$1(series).reverse();
22746 };
22747
22748 var define$1 = function(constructor, factory, prototype) {
22749   constructor.prototype = factory.prototype = prototype;
22750   prototype.constructor = constructor;
22751 };
22752
22753 function extend(parent, definition) {
22754   var prototype = Object.create(parent.prototype);
22755   for (var key in definition) prototype[key] = definition[key];
22756   return prototype;
22757 }
22758
22759 function Color() {}
22760
22761 var darker = 0.7;
22762 var brighter = 1 / darker;
22763
22764 var reHex3 = /^#([0-9a-f]{3})$/;
22765 var reHex6 = /^#([0-9a-f]{6})$/;
22766 var reRgbInteger = /^rgb\(\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*\)$/;
22767 var reRgbPercent = /^rgb\(\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*\)$/;
22768 var reRgbaInteger = /^rgba\(\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*,\s*([-+]?\d+)\s*,\s*([-+]?\d+(?:\.\d+)?)\s*\)$/;
22769 var reRgbaPercent = /^rgba\(\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)\s*\)$/;
22770 var reHslPercent = /^hsl\(\s*([-+]?\d+(?:\.\d+)?)\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*\)$/;
22771 var reHslaPercent = /^hsla\(\s*([-+]?\d+(?:\.\d+)?)\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)%\s*,\s*([-+]?\d+(?:\.\d+)?)\s*\)$/;
22772
22773 var named = {
22774   aliceblue: 0xf0f8ff,
22775   antiquewhite: 0xfaebd7,
22776   aqua: 0x00ffff,
22777   aquamarine: 0x7fffd4,
22778   azure: 0xf0ffff,
22779   beige: 0xf5f5dc,
22780   bisque: 0xffe4c4,
22781   black: 0x000000,
22782   blanchedalmond: 0xffebcd,
22783   blue: 0x0000ff,
22784   blueviolet: 0x8a2be2,
22785   brown: 0xa52a2a,
22786   burlywood: 0xdeb887,
22787   cadetblue: 0x5f9ea0,
22788   chartreuse: 0x7fff00,
22789   chocolate: 0xd2691e,
22790   coral: 0xff7f50,
22791   cornflowerblue: 0x6495ed,
22792   cornsilk: 0xfff8dc,
22793   crimson: 0xdc143c,
22794   cyan: 0x00ffff,
22795   darkblue: 0x00008b,
22796   darkcyan: 0x008b8b,
22797   darkgoldenrod: 0xb8860b,
22798   darkgray: 0xa9a9a9,
22799   darkgreen: 0x006400,
22800   darkgrey: 0xa9a9a9,
22801   darkkhaki: 0xbdb76b,
22802   darkmagenta: 0x8b008b,
22803   darkolivegreen: 0x556b2f,
22804   darkorange: 0xff8c00,
22805   darkorchid: 0x9932cc,
22806   darkred: 0x8b0000,
22807   darksalmon: 0xe9967a,
22808   darkseagreen: 0x8fbc8f,
22809   darkslateblue: 0x483d8b,
22810   darkslategray: 0x2f4f4f,
22811   darkslategrey: 0x2f4f4f,
22812   darkturquoise: 0x00ced1,
22813   darkviolet: 0x9400d3,
22814   deeppink: 0xff1493,
22815   deepskyblue: 0x00bfff,
22816   dimgray: 0x696969,
22817   dimgrey: 0x696969,
22818   dodgerblue: 0x1e90ff,
22819   firebrick: 0xb22222,
22820   floralwhite: 0xfffaf0,
22821   forestgreen: 0x228b22,
22822   fuchsia: 0xff00ff,
22823   gainsboro: 0xdcdcdc,
22824   ghostwhite: 0xf8f8ff,
22825   gold: 0xffd700,
22826   goldenrod: 0xdaa520,
22827   gray: 0x808080,
22828   green: 0x008000,
22829   greenyellow: 0xadff2f,
22830   grey: 0x808080,
22831   honeydew: 0xf0fff0,
22832   hotpink: 0xff69b4,
22833   indianred: 0xcd5c5c,
22834   indigo: 0x4b0082,
22835   ivory: 0xfffff0,
22836   khaki: 0xf0e68c,
22837   lavender: 0xe6e6fa,
22838   lavenderblush: 0xfff0f5,
22839   lawngreen: 0x7cfc00,
22840   lemonchiffon: 0xfffacd,
22841   lightblue: 0xadd8e6,
22842   lightcoral: 0xf08080,
22843   lightcyan: 0xe0ffff,
22844   lightgoldenrodyellow: 0xfafad2,
22845   lightgray: 0xd3d3d3,
22846   lightgreen: 0x90ee90,
22847   lightgrey: 0xd3d3d3,
22848   lightpink: 0xffb6c1,
22849   lightsalmon: 0xffa07a,
22850   lightseagreen: 0x20b2aa,
22851   lightskyblue: 0x87cefa,
22852   lightslategray: 0x778899,
22853   lightslategrey: 0x778899,
22854   lightsteelblue: 0xb0c4de,
22855   lightyellow: 0xffffe0,
22856   lime: 0x00ff00,
22857   limegreen: 0x32cd32,
22858   linen: 0xfaf0e6,
22859   magenta: 0xff00ff,
22860   maroon: 0x800000,
22861   mediumaquamarine: 0x66cdaa,
22862   mediumblue: 0x0000cd,
22863   mediumorchid: 0xba55d3,
22864   mediumpurple: 0x9370db,
22865   mediumseagreen: 0x3cb371,
22866   mediumslateblue: 0x7b68ee,
22867   mediumspringgreen: 0x00fa9a,
22868   mediumturquoise: 0x48d1cc,
22869   mediumvioletred: 0xc71585,
22870   midnightblue: 0x191970,
22871   mintcream: 0xf5fffa,
22872   mistyrose: 0xffe4e1,
22873   moccasin: 0xffe4b5,
22874   navajowhite: 0xffdead,
22875   navy: 0x000080,
22876   oldlace: 0xfdf5e6,
22877   olive: 0x808000,
22878   olivedrab: 0x6b8e23,
22879   orange: 0xffa500,
22880   orangered: 0xff4500,
22881   orchid: 0xda70d6,
22882   palegoldenrod: 0xeee8aa,
22883   palegreen: 0x98fb98,
22884   paleturquoise: 0xafeeee,
22885   palevioletred: 0xdb7093,
22886   papayawhip: 0xffefd5,
22887   peachpuff: 0xffdab9,
22888   peru: 0xcd853f,
22889   pink: 0xffc0cb,
22890   plum: 0xdda0dd,
22891   powderblue: 0xb0e0e6,
22892   purple: 0x800080,
22893   rebeccapurple: 0x663399,
22894   red: 0xff0000,
22895   rosybrown: 0xbc8f8f,
22896   royalblue: 0x4169e1,
22897   saddlebrown: 0x8b4513,
22898   salmon: 0xfa8072,
22899   sandybrown: 0xf4a460,
22900   seagreen: 0x2e8b57,
22901   seashell: 0xfff5ee,
22902   sienna: 0xa0522d,
22903   silver: 0xc0c0c0,
22904   skyblue: 0x87ceeb,
22905   slateblue: 0x6a5acd,
22906   slategray: 0x708090,
22907   slategrey: 0x708090,
22908   snow: 0xfffafa,
22909   springgreen: 0x00ff7f,
22910   steelblue: 0x4682b4,
22911   tan: 0xd2b48c,
22912   teal: 0x008080,
22913   thistle: 0xd8bfd8,
22914   tomato: 0xff6347,
22915   turquoise: 0x40e0d0,
22916   violet: 0xee82ee,
22917   wheat: 0xf5deb3,
22918   white: 0xffffff,
22919   whitesmoke: 0xf5f5f5,
22920   yellow: 0xffff00,
22921   yellowgreen: 0x9acd32
22922 };
22923
22924 define$1(Color, color, {
22925   displayable: function() {
22926     return this.rgb().displayable();
22927   },
22928   toString: function() {
22929     return this.rgb() + "";
22930   }
22931 });
22932
22933 function color(format) {
22934   var m;
22935   format = (format + "").trim().toLowerCase();
22936   return (m = reHex3.exec(format)) ? (m = parseInt(m[1], 16), new Rgb((m >> 8 & 0xf) | (m >> 4 & 0x0f0), (m >> 4 & 0xf) | (m & 0xf0), ((m & 0xf) << 4) | (m & 0xf), 1)) // #f00
22937       : (m = reHex6.exec(format)) ? rgbn(parseInt(m[1], 16)) // #ff0000
22938       : (m = reRgbInteger.exec(format)) ? new Rgb(m[1], m[2], m[3], 1) // rgb(255, 0, 0)
22939       : (m = reRgbPercent.exec(format)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) // rgb(100%, 0%, 0%)
22940       : (m = reRgbaInteger.exec(format)) ? rgba(m[1], m[2], m[3], m[4]) // rgba(255, 0, 0, 1)
22941       : (m = reRgbaPercent.exec(format)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) // rgb(100%, 0%, 0%, 1)
22942       : (m = reHslPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) // hsl(120, 50%, 50%)
22943       : (m = reHslaPercent.exec(format)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) // hsla(120, 50%, 50%, 1)
22944       : named.hasOwnProperty(format) ? rgbn(named[format])
22945       : format === "transparent" ? new Rgb(NaN, NaN, NaN, 0)
22946       : null;
22947 }
22948
22949 function rgbn(n) {
22950   return new Rgb(n >> 16 & 0xff, n >> 8 & 0xff, n & 0xff, 1);
22951 }
22952
22953 function rgba(r, g, b, a) {
22954   if (a <= 0) r = g = b = NaN;
22955   return new Rgb(r, g, b, a);
22956 }
22957
22958 function rgbConvert(o) {
22959   if (!(o instanceof Color)) o = color(o);
22960   if (!o) return new Rgb;
22961   o = o.rgb();
22962   return new Rgb(o.r, o.g, o.b, o.opacity);
22963 }
22964
22965 function rgb(r, g, b, opacity) {
22966   return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity == null ? 1 : opacity);
22967 }
22968
22969 function Rgb(r, g, b, opacity) {
22970   this.r = +r;
22971   this.g = +g;
22972   this.b = +b;
22973   this.opacity = +opacity;
22974 }
22975
22976 define$1(Rgb, rgb, extend(Color, {
22977   brighter: function(k) {
22978     k = k == null ? brighter : Math.pow(brighter, k);
22979     return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
22980   },
22981   darker: function(k) {
22982     k = k == null ? darker : Math.pow(darker, k);
22983     return new Rgb(this.r * k, this.g * k, this.b * k, this.opacity);
22984   },
22985   rgb: function() {
22986     return this;
22987   },
22988   displayable: function() {
22989     return (0 <= this.r && this.r <= 255)
22990         && (0 <= this.g && this.g <= 255)
22991         && (0 <= this.b && this.b <= 255)
22992         && (0 <= this.opacity && this.opacity <= 1);
22993   },
22994   toString: function() {
22995     var a = this.opacity; a = isNaN(a) ? 1 : Math.max(0, Math.min(1, a));
22996     return (a === 1 ? "rgb(" : "rgba(")
22997         + Math.max(0, Math.min(255, Math.round(this.r) || 0)) + ", "
22998         + Math.max(0, Math.min(255, Math.round(this.g) || 0)) + ", "
22999         + Math.max(0, Math.min(255, Math.round(this.b) || 0))
23000         + (a === 1 ? ")" : ", " + a + ")");
23001   }
23002 }));
23003
23004 function hsla(h, s, l, a) {
23005   if (a <= 0) h = s = l = NaN;
23006   else if (l <= 0 || l >= 1) h = s = NaN;
23007   else if (s <= 0) h = NaN;
23008   return new Hsl(h, s, l, a);
23009 }
23010
23011 function hslConvert(o) {
23012   if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);
23013   if (!(o instanceof Color)) o = color(o);
23014   if (!o) return new Hsl;
23015   if (o instanceof Hsl) return o;
23016   o = o.rgb();
23017   var r = o.r / 255,
23018       g = o.g / 255,
23019       b = o.b / 255,
23020       min = Math.min(r, g, b),
23021       max = Math.max(r, g, b),
23022       h = NaN,
23023       s = max - min,
23024       l = (max + min) / 2;
23025   if (s) {
23026     if (r === max) h = (g - b) / s + (g < b) * 6;
23027     else if (g === max) h = (b - r) / s + 2;
23028     else h = (r - g) / s + 4;
23029     s /= l < 0.5 ? max + min : 2 - max - min;
23030     h *= 60;
23031   } else {
23032     s = l > 0 && l < 1 ? 0 : h;
23033   }
23034   return new Hsl(h, s, l, o.opacity);
23035 }
23036
23037 function hsl(h, s, l, opacity) {
23038   return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s, l, opacity == null ? 1 : opacity);
23039 }
23040
23041 function Hsl(h, s, l, opacity) {
23042   this.h = +h;
23043   this.s = +s;
23044   this.l = +l;
23045   this.opacity = +opacity;
23046 }
23047
23048 define$1(Hsl, hsl, extend(Color, {
23049   brighter: function(k) {
23050     k = k == null ? brighter : Math.pow(brighter, k);
23051     return new Hsl(this.h, this.s, this.l * k, this.opacity);
23052   },
23053   darker: function(k) {
23054     k = k == null ? darker : Math.pow(darker, k);
23055     return new Hsl(this.h, this.s, this.l * k, this.opacity);
23056   },
23057   rgb: function() {
23058     var h = this.h % 360 + (this.h < 0) * 360,
23059         s = isNaN(h) || isNaN(this.s) ? 0 : this.s,
23060         l = this.l,
23061         m2 = l + (l < 0.5 ? l : 1 - l) * s,
23062         m1 = 2 * l - m2;
23063     return new Rgb(
23064       hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2),
23065       hsl2rgb(h, m1, m2),
23066       hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2),
23067       this.opacity
23068     );
23069   },
23070   displayable: function() {
23071     return (0 <= this.s && this.s <= 1 || isNaN(this.s))
23072         && (0 <= this.l && this.l <= 1)
23073         && (0 <= this.opacity && this.opacity <= 1);
23074   }
23075 }));
23076
23077 /* From FvD 13.37, CSS Color Module Level 3 */
23078 function hsl2rgb(h, m1, m2) {
23079   return (h < 60 ? m1 + (m2 - m1) * h / 60
23080       : h < 180 ? m2
23081       : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60
23082       : m1) * 255;
23083 }
23084
23085 var deg2rad = Math.PI / 180;
23086 var rad2deg = 180 / Math.PI;
23087
23088 var Kn = 18;
23089 var Xn = 0.950470;
23090 var Yn = 1;
23091 var Zn = 1.088830;
23092 var t0 = 4 / 29;
23093 var t1 = 6 / 29;
23094 var t2 = 3 * t1 * t1;
23095 var t3 = t1 * t1 * t1;
23096
23097 function labConvert(o) {
23098   if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity);
23099   if (o instanceof Hcl) {
23100     var h = o.h * deg2rad;
23101     return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity);
23102   }
23103   if (!(o instanceof Rgb)) o = rgbConvert(o);
23104   var b = rgb2xyz(o.r),
23105       a = rgb2xyz(o.g),
23106       l = rgb2xyz(o.b),
23107       x = xyz2lab((0.4124564 * b + 0.3575761 * a + 0.1804375 * l) / Xn),
23108       y = xyz2lab((0.2126729 * b + 0.7151522 * a + 0.0721750 * l) / Yn),
23109       z = xyz2lab((0.0193339 * b + 0.1191920 * a + 0.9503041 * l) / Zn);
23110   return new Lab(116 * y - 16, 500 * (x - y), 200 * (y - z), o.opacity);
23111 }
23112
23113 function lab(l, a, b, opacity) {
23114   return arguments.length === 1 ? labConvert(l) : new Lab(l, a, b, opacity == null ? 1 : opacity);
23115 }
23116
23117 function Lab(l, a, b, opacity) {
23118   this.l = +l;
23119   this.a = +a;
23120   this.b = +b;
23121   this.opacity = +opacity;
23122 }
23123
23124 define$1(Lab, lab, extend(Color, {
23125   brighter: function(k) {
23126     return new Lab(this.l + Kn * (k == null ? 1 : k), this.a, this.b, this.opacity);
23127   },
23128   darker: function(k) {
23129     return new Lab(this.l - Kn * (k == null ? 1 : k), this.a, this.b, this.opacity);
23130   },
23131   rgb: function() {
23132     var y = (this.l + 16) / 116,
23133         x = isNaN(this.a) ? y : y + this.a / 500,
23134         z = isNaN(this.b) ? y : y - this.b / 200;
23135     y = Yn * lab2xyz(y);
23136     x = Xn * lab2xyz(x);
23137     z = Zn * lab2xyz(z);
23138     return new Rgb(
23139       xyz2rgb( 3.2404542 * x - 1.5371385 * y - 0.4985314 * z), // D65 -> sRGB
23140       xyz2rgb(-0.9692660 * x + 1.8760108 * y + 0.0415560 * z),
23141       xyz2rgb( 0.0556434 * x - 0.2040259 * y + 1.0572252 * z),
23142       this.opacity
23143     );
23144   }
23145 }));
23146
23147 function xyz2lab(t) {
23148   return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0;
23149 }
23150
23151 function lab2xyz(t) {
23152   return t > t1 ? t * t * t : t2 * (t - t0);
23153 }
23154
23155 function xyz2rgb(x) {
23156   return 255 * (x <= 0.0031308 ? 12.92 * x : 1.055 * Math.pow(x, 1 / 2.4) - 0.055);
23157 }
23158
23159 function rgb2xyz(x) {
23160   return (x /= 255) <= 0.04045 ? x / 12.92 : Math.pow((x + 0.055) / 1.055, 2.4);
23161 }
23162
23163 function hclConvert(o) {
23164   if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity);
23165   if (!(o instanceof Lab)) o = labConvert(o);
23166   var h = Math.atan2(o.b, o.a) * rad2deg;
23167   return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity);
23168 }
23169
23170 function hcl(h, c, l, opacity) {
23171   return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c, l, opacity == null ? 1 : opacity);
23172 }
23173
23174 function Hcl(h, c, l, opacity) {
23175   this.h = +h;
23176   this.c = +c;
23177   this.l = +l;
23178   this.opacity = +opacity;
23179 }
23180
23181 define$1(Hcl, hcl, extend(Color, {
23182   brighter: function(k) {
23183     return new Hcl(this.h, this.c, this.l + Kn * (k == null ? 1 : k), this.opacity);
23184   },
23185   darker: function(k) {
23186     return new Hcl(this.h, this.c, this.l - Kn * (k == null ? 1 : k), this.opacity);
23187   },
23188   rgb: function() {
23189     return labConvert(this).rgb();
23190   }
23191 }));
23192
23193 var A = -0.14861;
23194 var B = +1.78277;
23195 var C = -0.29227;
23196 var D = -0.90649;
23197 var E = +1.97294;
23198 var ED = E * D;
23199 var EB = E * B;
23200 var BC_DA = B * C - D * A;
23201
23202 function cubehelixConvert(o) {
23203   if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity);
23204   if (!(o instanceof Rgb)) o = rgbConvert(o);
23205   var r = o.r / 255,
23206       g = o.g / 255,
23207       b = o.b / 255,
23208       l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB),
23209       bl = b - l,
23210       k = (E * (g - l) - C * bl) / D,
23211       s = Math.sqrt(k * k + bl * bl) / (E * l * (1 - l)), // NaN if l=0 or l=1
23212       h = s ? Math.atan2(k, bl) * rad2deg - 120 : NaN;
23213   return new Cubehelix(h < 0 ? h + 360 : h, s, l, o.opacity);
23214 }
23215
23216 function cubehelix(h, s, l, opacity) {
23217   return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s, l, opacity == null ? 1 : opacity);
23218 }
23219
23220 function Cubehelix(h, s, l, opacity) {
23221   this.h = +h;
23222   this.s = +s;
23223   this.l = +l;
23224   this.opacity = +opacity;
23225 }
23226
23227 define$1(Cubehelix, cubehelix, extend(Color, {
23228   brighter: function(k) {
23229     k = k == null ? brighter : Math.pow(brighter, k);
23230     return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
23231   },
23232   darker: function(k) {
23233     k = k == null ? darker : Math.pow(darker, k);
23234     return new Cubehelix(this.h, this.s, this.l * k, this.opacity);
23235   },
23236   rgb: function() {
23237     var h = isNaN(this.h) ? 0 : (this.h + 120) * deg2rad,
23238         l = +this.l,
23239         a = isNaN(this.s) ? 0 : this.s * l * (1 - l),
23240         cosh = Math.cos(h),
23241         sinh = Math.sin(h);
23242     return new Rgb(
23243       255 * (l + a * (A * cosh + B * sinh)),
23244       255 * (l + a * (C * cosh + D * sinh)),
23245       255 * (l + a * (E * cosh)),
23246       this.opacity
23247     );
23248   }
23249 }));
23250
23251 function basis$1(t1, v0, v1, v2, v3) {
23252   var t2 = t1 * t1, t3 = t2 * t1;
23253   return ((1 - 3 * t1 + 3 * t2 - t3) * v0
23254       + (4 - 6 * t2 + 3 * t3) * v1
23255       + (1 + 3 * t1 + 3 * t2 - 3 * t3) * v2
23256       + t3 * v3) / 6;
23257 }
23258
23259 var basis$2 = function(values) {
23260   var n = values.length - 1;
23261   return function(t) {
23262     var i = t <= 0 ? (t = 0) : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n),
23263         v1 = values[i],
23264         v2 = values[i + 1],
23265         v0 = i > 0 ? values[i - 1] : 2 * v1 - v2,
23266         v3 = i < n - 1 ? values[i + 2] : 2 * v2 - v1;
23267     return basis$1((t - i / n) * n, v0, v1, v2, v3);
23268   };
23269 };
23270
23271 var basisClosed$1 = function(values) {
23272   var n = values.length;
23273   return function(t) {
23274     var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n),
23275         v0 = values[(i + n - 1) % n],
23276         v1 = values[i % n],
23277         v2 = values[(i + 1) % n],
23278         v3 = values[(i + 2) % n];
23279     return basis$1((t - i / n) * n, v0, v1, v2, v3);
23280   };
23281 };
23282
23283 var constant$3 = function(x) {
23284   return function() {
23285     return x;
23286   };
23287 };
23288
23289 function linear$1(a, d) {
23290   return function(t) {
23291     return a + t * d;
23292   };
23293 }
23294
23295 function exponential$1(a, b, y) {
23296   return a = Math.pow(a, y), b = Math.pow(b, y) - a, y = 1 / y, function(t) {
23297     return Math.pow(a + t * b, y);
23298   };
23299 }
23300
23301 function hue(a, b) {
23302   var d = b - a;
23303   return d ? linear$1(a, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant$3(isNaN(a) ? b : a);
23304 }
23305
23306 function gamma(y) {
23307   return (y = +y) === 1 ? nogamma : function(a, b) {
23308     return b - a ? exponential$1(a, b, y) : constant$3(isNaN(a) ? b : a);
23309   };
23310 }
23311
23312 function nogamma(a, b) {
23313   var d = b - a;
23314   return d ? linear$1(a, d) : constant$3(isNaN(a) ? b : a);
23315 }
23316
23317 var interpolateRgb = (function rgbGamma(y) {
23318   var color$$1 = gamma(y);
23319
23320   function rgb$$1(start, end) {
23321     var r = color$$1((start = rgb(start)).r, (end = rgb(end)).r),
23322         g = color$$1(start.g, end.g),
23323         b = color$$1(start.b, end.b),
23324         opacity = color$$1(start.opacity, end.opacity);
23325     return function(t) {
23326       start.r = r(t);
23327       start.g = g(t);
23328       start.b = b(t);
23329       start.opacity = opacity(t);
23330       return start + "";
23331     };
23332   }
23333
23334   rgb$$1.gamma = rgbGamma;
23335
23336   return rgb$$1;
23337 })(1);
23338
23339 function rgbSpline(spline) {
23340   return function(colors) {
23341     var n = colors.length,
23342         r = new Array(n),
23343         g = new Array(n),
23344         b = new Array(n),
23345         i, color$$1;
23346     for (i = 0; i < n; ++i) {
23347       color$$1 = rgb(colors[i]);
23348       r[i] = color$$1.r || 0;
23349       g[i] = color$$1.g || 0;
23350       b[i] = color$$1.b || 0;
23351     }
23352     r = spline(r);
23353     g = spline(g);
23354     b = spline(b);
23355     color$$1.opacity = 1;
23356     return function(t) {
23357       color$$1.r = r(t);
23358       color$$1.g = g(t);
23359       color$$1.b = b(t);
23360       return color$$1 + "";
23361     };
23362   };
23363 }
23364
23365 var rgbBasis = rgbSpline(basis$2);
23366 var rgbBasisClosed = rgbSpline(basisClosed$1);
23367
23368 var array$1 = function(a, b) {
23369   var nb = b ? b.length : 0,
23370       na = a ? Math.min(nb, a.length) : 0,
23371       x = new Array(nb),
23372       c = new Array(nb),
23373       i;
23374
23375   for (i = 0; i < na; ++i) x[i] = interpolate(a[i], b[i]);
23376   for (; i < nb; ++i) c[i] = b[i];
23377
23378   return function(t) {
23379     for (i = 0; i < na; ++i) c[i] = x[i](t);
23380     return c;
23381   };
23382 };
23383
23384 var date = function(a, b) {
23385   var d = new Date;
23386   return a = +a, b -= a, function(t) {
23387     return d.setTime(a + b * t), d;
23388   };
23389 };
23390
23391 var interpolateNumber = function(a, b) {
23392   return a = +a, b -= a, function(t) {
23393     return a + b * t;
23394   };
23395 };
23396
23397 var object = function(a, b) {
23398   var i = {},
23399       c = {},
23400       k;
23401
23402   if (a === null || typeof a !== "object") a = {};
23403   if (b === null || typeof b !== "object") b = {};
23404
23405   for (k in b) {
23406     if (k in a) {
23407       i[k] = interpolate(a[k], b[k]);
23408     } else {
23409       c[k] = b[k];
23410     }
23411   }
23412
23413   return function(t) {
23414     for (k in i) c[k] = i[k](t);
23415     return c;
23416   };
23417 };
23418
23419 var reA = /[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g;
23420 var reB = new RegExp(reA.source, "g");
23421
23422 function zero(b) {
23423   return function() {
23424     return b;
23425   };
23426 }
23427
23428 function one(b) {
23429   return function(t) {
23430     return b(t) + "";
23431   };
23432 }
23433
23434 var interpolateString = function(a, b) {
23435   var bi = reA.lastIndex = reB.lastIndex = 0, // scan index for next number in b
23436       am, // current match in a
23437       bm, // current match in b
23438       bs, // string preceding current number in b, if any
23439       i = -1, // index in s
23440       s = [], // string constants and placeholders
23441       q = []; // number interpolators
23442
23443   // Coerce inputs to strings.
23444   a = a + "", b = b + "";
23445
23446   // Interpolate pairs of numbers in a & b.
23447   while ((am = reA.exec(a))
23448       && (bm = reB.exec(b))) {
23449     if ((bs = bm.index) > bi) { // a string precedes the next number in b
23450       bs = b.slice(bi, bs);
23451       if (s[i]) s[i] += bs; // coalesce with previous string
23452       else s[++i] = bs;
23453     }
23454     if ((am = am[0]) === (bm = bm[0])) { // numbers in a & b match
23455       if (s[i]) s[i] += bm; // coalesce with previous string
23456       else s[++i] = bm;
23457     } else { // interpolate non-matching numbers
23458       s[++i] = null;
23459       q.push({i: i, x: interpolateNumber(am, bm)});
23460     }
23461     bi = reB.lastIndex;
23462   }
23463
23464   // Add remains of b.
23465   if (bi < b.length) {
23466     bs = b.slice(bi);
23467     if (s[i]) s[i] += bs; // coalesce with previous string
23468     else s[++i] = bs;
23469   }
23470
23471   // Special optimization for only a single match.
23472   // Otherwise, interpolate each of the numbers and rejoin the string.
23473   return s.length < 2 ? (q[0]
23474       ? one(q[0].x)
23475       : zero(b))
23476       : (b = q.length, function(t) {
23477           for (var i = 0, o; i < b; ++i) s[(o = q[i]).i] = o.x(t);
23478           return s.join("");
23479         });
23480 };
23481
23482 var interpolate = function(a, b) {
23483   var t = typeof b, c;
23484   return b == null || t === "boolean" ? constant$3(b)
23485       : (t === "number" ? interpolateNumber
23486       : t === "string" ? ((c = color(b)) ? (b = c, interpolateRgb) : interpolateString)
23487       : b instanceof color ? interpolateRgb
23488       : b instanceof Date ? date
23489       : Array.isArray(b) ? array$1
23490       : isNaN(b) ? object
23491       : interpolateNumber)(a, b);
23492 };
23493
23494 var interpolateRound = function(a, b) {
23495   return a = +a, b -= a, function(t) {
23496     return Math.round(a + b * t);
23497   };
23498 };
23499
23500 var degrees = 180 / Math.PI;
23501
23502 var identity$2 = {
23503   translateX: 0,
23504   translateY: 0,
23505   rotate: 0,
23506   skewX: 0,
23507   scaleX: 1,
23508   scaleY: 1
23509 };
23510
23511 var decompose = function(a, b, c, d, e, f) {
23512   var scaleX, scaleY, skewX;
23513   if (scaleX = Math.sqrt(a * a + b * b)) a /= scaleX, b /= scaleX;
23514   if (skewX = a * c + b * d) c -= a * skewX, d -= b * skewX;
23515   if (scaleY = Math.sqrt(c * c + d * d)) c /= scaleY, d /= scaleY, skewX /= scaleY;
23516   if (a * d < b * c) a = -a, b = -b, skewX = -skewX, scaleX = -scaleX;
23517   return {
23518     translateX: e,
23519     translateY: f,
23520     rotate: Math.atan2(b, a) * degrees,
23521     skewX: Math.atan(skewX) * degrees,
23522     scaleX: scaleX,
23523     scaleY: scaleY
23524   };
23525 };
23526
23527 var cssNode;
23528 var cssRoot;
23529 var cssView;
23530 var svgNode;
23531
23532 function parseCss(value) {
23533   if (value === "none") return identity$2;
23534   if (!cssNode) cssNode = document.createElement("DIV"), cssRoot = document.documentElement, cssView = document.defaultView;
23535   cssNode.style.transform = value;
23536   value = cssView.getComputedStyle(cssRoot.appendChild(cssNode), null).getPropertyValue("transform");
23537   cssRoot.removeChild(cssNode);
23538   value = value.slice(7, -1).split(",");
23539   return decompose(+value[0], +value[1], +value[2], +value[3], +value[4], +value[5]);
23540 }
23541
23542 function parseSvg(value) {
23543   if (value == null) return identity$2;
23544   if (!svgNode) svgNode = document.createElementNS("http://www.w3.org/2000/svg", "g");
23545   svgNode.setAttribute("transform", value);
23546   if (!(value = svgNode.transform.baseVal.consolidate())) return identity$2;
23547   value = value.matrix;
23548   return decompose(value.a, value.b, value.c, value.d, value.e, value.f);
23549 }
23550
23551 function interpolateTransform(parse, pxComma, pxParen, degParen) {
23552
23553   function pop(s) {
23554     return s.length ? s.pop() + " " : "";
23555   }
23556
23557   function translate(xa, ya, xb, yb, s, q) {
23558     if (xa !== xb || ya !== yb) {
23559       var i = s.push("translate(", null, pxComma, null, pxParen);
23560       q.push({i: i - 4, x: interpolateNumber(xa, xb)}, {i: i - 2, x: interpolateNumber(ya, yb)});
23561     } else if (xb || yb) {
23562       s.push("translate(" + xb + pxComma + yb + pxParen);
23563     }
23564   }
23565
23566   function rotate(a, b, s, q) {
23567     if (a !== b) {
23568       if (a - b > 180) b += 360; else if (b - a > 180) a += 360; // shortest path
23569       q.push({i: s.push(pop(s) + "rotate(", null, degParen) - 2, x: interpolateNumber(a, b)});
23570     } else if (b) {
23571       s.push(pop(s) + "rotate(" + b + degParen);
23572     }
23573   }
23574
23575   function skewX(a, b, s, q) {
23576     if (a !== b) {
23577       q.push({i: s.push(pop(s) + "skewX(", null, degParen) - 2, x: interpolateNumber(a, b)});
23578     } else if (b) {
23579       s.push(pop(s) + "skewX(" + b + degParen);
23580     }
23581   }
23582
23583   function scale(xa, ya, xb, yb, s, q) {
23584     if (xa !== xb || ya !== yb) {
23585       var i = s.push(pop(s) + "scale(", null, ",", null, ")");
23586       q.push({i: i - 4, x: interpolateNumber(xa, xb)}, {i: i - 2, x: interpolateNumber(ya, yb)});
23587     } else if (xb !== 1 || yb !== 1) {
23588       s.push(pop(s) + "scale(" + xb + "," + yb + ")");
23589     }
23590   }
23591
23592   return function(a, b) {
23593     var s = [], // string constants and placeholders
23594         q = []; // number interpolators
23595     a = parse(a), b = parse(b);
23596     translate(a.translateX, a.translateY, b.translateX, b.translateY, s, q);
23597     rotate(a.rotate, b.rotate, s, q);
23598     skewX(a.skewX, b.skewX, s, q);
23599     scale(a.scaleX, a.scaleY, b.scaleX, b.scaleY, s, q);
23600     a = b = null; // gc
23601     return function(t) {
23602       var i = -1, n = q.length, o;
23603       while (++i < n) s[(o = q[i]).i] = o.x(t);
23604       return s.join("");
23605     };
23606   };
23607 }
23608
23609 var interpolateTransformCss = interpolateTransform(parseCss, "px, ", "px)", "deg)");
23610 var interpolateTransformSvg = interpolateTransform(parseSvg, ", ", ")", ")");
23611
23612 var rho = Math.SQRT2;
23613 var rho2 = 2;
23614 var rho4 = 4;
23615 var epsilon2 = 1e-12;
23616
23617 function cosh(x) {
23618   return ((x = Math.exp(x)) + 1 / x) / 2;
23619 }
23620
23621 function sinh(x) {
23622   return ((x = Math.exp(x)) - 1 / x) / 2;
23623 }
23624
23625 function tanh(x) {
23626   return ((x = Math.exp(2 * x)) - 1) / (x + 1);
23627 }
23628
23629 // p0 = [ux0, uy0, w0]
23630 // p1 = [ux1, uy1, w1]
23631 var interpolateZoom = function(p0, p1) {
23632   var ux0 = p0[0], uy0 = p0[1], w0 = p0[2],
23633       ux1 = p1[0], uy1 = p1[1], w1 = p1[2],
23634       dx = ux1 - ux0,
23635       dy = uy1 - uy0,
23636       d2 = dx * dx + dy * dy,
23637       i,
23638       S;
23639
23640   // Special case for u0 ≅ u1.
23641   if (d2 < epsilon2) {
23642     S = Math.log(w1 / w0) / rho;
23643     i = function(t) {
23644       return [
23645         ux0 + t * dx,
23646         uy0 + t * dy,
23647         w0 * Math.exp(rho * t * S)
23648       ];
23649     };
23650   }
23651
23652   // General case.
23653   else {
23654     var d1 = Math.sqrt(d2),
23655         b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1),
23656         b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1),
23657         r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0),
23658         r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1);
23659     S = (r1 - r0) / rho;
23660     i = function(t) {
23661       var s = t * S,
23662           coshr0 = cosh(r0),
23663           u = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s + r0) - sinh(r0));
23664       return [
23665         ux0 + u * dx,
23666         uy0 + u * dy,
23667         w0 * coshr0 / cosh(rho * s + r0)
23668       ];
23669     };
23670   }
23671
23672   i.duration = S * 1000;
23673
23674   return i;
23675 };
23676
23677 function hsl$1(hue$$1) {
23678   return function(start, end) {
23679     var h = hue$$1((start = hsl(start)).h, (end = hsl(end)).h),
23680         s = nogamma(start.s, end.s),
23681         l = nogamma(start.l, end.l),
23682         opacity = nogamma(start.opacity, end.opacity);
23683     return function(t) {
23684       start.h = h(t);
23685       start.s = s(t);
23686       start.l = l(t);
23687       start.opacity = opacity(t);
23688       return start + "";
23689     };
23690   }
23691 }
23692
23693 var hsl$2 = hsl$1(hue);
23694 var hslLong = hsl$1(nogamma);
23695
23696 function lab$1(start, end) {
23697   var l = nogamma((start = lab(start)).l, (end = lab(end)).l),
23698       a = nogamma(start.a, end.a),
23699       b = nogamma(start.b, end.b),
23700       opacity = nogamma(start.opacity, end.opacity);
23701   return function(t) {
23702     start.l = l(t);
23703     start.a = a(t);
23704     start.b = b(t);
23705     start.opacity = opacity(t);
23706     return start + "";
23707   };
23708 }
23709
23710 function hcl$1(hue$$1) {
23711   return function(start, end) {
23712     var h = hue$$1((start = hcl(start)).h, (end = hcl(end)).h),
23713         c = nogamma(start.c, end.c),
23714         l = nogamma(start.l, end.l),
23715         opacity = nogamma(start.opacity, end.opacity);
23716     return function(t) {
23717       start.h = h(t);
23718       start.c = c(t);
23719       start.l = l(t);
23720       start.opacity = opacity(t);
23721       return start + "";
23722     };
23723   }
23724 }
23725
23726 var hcl$2 = hcl$1(hue);
23727 var hclLong = hcl$1(nogamma);
23728
23729 function cubehelix$1(hue$$1) {
23730   return (function cubehelixGamma(y) {
23731     y = +y;
23732
23733     function cubehelix$$1(start, end) {
23734       var h = hue$$1((start = cubehelix(start)).h, (end = cubehelix(end)).h),
23735           s = nogamma(start.s, end.s),
23736           l = nogamma(start.l, end.l),
23737           opacity = nogamma(start.opacity, end.opacity);
23738       return function(t) {
23739         start.h = h(t);
23740         start.s = s(t);
23741         start.l = l(Math.pow(t, y));
23742         start.opacity = opacity(t);
23743         return start + "";
23744       };
23745     }
23746
23747     cubehelix$$1.gamma = cubehelixGamma;
23748
23749     return cubehelix$$1;
23750   })(1);
23751 }
23752
23753 var cubehelix$2 = cubehelix$1(hue);
23754 var cubehelixLong = cubehelix$1(nogamma);
23755
23756 var quantize = function(interpolator, n) {
23757   var samples = new Array(n);
23758   for (var i = 0; i < n; ++i) samples[i] = interpolator(i / (n - 1));
23759   return samples;
23760 };
23761
23762 var noop$1 = {value: function() {}};
23763
23764 function dispatch() {
23765   for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) {
23766     if (!(t = arguments[i] + "") || (t in _)) throw new Error("illegal type: " + t);
23767     _[t] = [];
23768   }
23769   return new Dispatch(_);
23770 }
23771
23772 function Dispatch(_) {
23773   this._ = _;
23774 }
23775
23776 function parseTypenames(typenames, types) {
23777   return typenames.trim().split(/^|\s+/).map(function(t) {
23778     var name = "", i = t.indexOf(".");
23779     if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
23780     if (t && !types.hasOwnProperty(t)) throw new Error("unknown type: " + t);
23781     return {type: t, name: name};
23782   });
23783 }
23784
23785 Dispatch.prototype = dispatch.prototype = {
23786   constructor: Dispatch,
23787   on: function(typename, callback) {
23788     var _ = this._,
23789         T = parseTypenames(typename + "", _),
23790         t,
23791         i = -1,
23792         n = T.length;
23793
23794     // If no callback was specified, return the callback of the given type and name.
23795     if (arguments.length < 2) {
23796       while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t;
23797       return;
23798     }
23799
23800     // If a type was specified, set the callback for the given type and name.
23801     // Otherwise, if a null callback was specified, remove callbacks of the given name.
23802     if (callback != null && typeof callback !== "function") throw new Error("invalid callback: " + callback);
23803     while (++i < n) {
23804       if (t = (typename = T[i]).type) _[t] = set$2(_[t], typename.name, callback);
23805       else if (callback == null) for (t in _) _[t] = set$2(_[t], typename.name, null);
23806     }
23807
23808     return this;
23809   },
23810   copy: function() {
23811     var copy = {}, _ = this._;
23812     for (var t in _) copy[t] = _[t].slice();
23813     return new Dispatch(copy);
23814   },
23815   call: function(type, that) {
23816     if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2];
23817     if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
23818     for (t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);
23819   },
23820   apply: function(type, that, args) {
23821     if (!this._.hasOwnProperty(type)) throw new Error("unknown type: " + type);
23822     for (var t = this._[type], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);
23823   }
23824 };
23825
23826 function get(type, name) {
23827   for (var i = 0, n = type.length, c; i < n; ++i) {
23828     if ((c = type[i]).name === name) {
23829       return c.value;
23830     }
23831   }
23832 }
23833
23834 function set$2(type, name, callback) {
23835   for (var i = 0, n = type.length; i < n; ++i) {
23836     if (type[i].name === name) {
23837       type[i] = noop$1, type = type.slice(0, i).concat(type.slice(i + 1));
23838       break;
23839     }
23840   }
23841   if (callback != null) type.push({name: name, value: callback});
23842   return type;
23843 }
23844
23845 function objectConverter(columns) {
23846   return new Function("d", "return {" + columns.map(function(name, i) {
23847     return JSON.stringify(name) + ": d[" + i + "]";
23848   }).join(",") + "}");
23849 }
23850
23851 function customConverter(columns, f) {
23852   var object = objectConverter(columns);
23853   return function(row, i) {
23854     return f(object(row), i, columns);
23855   };
23856 }
23857
23858 // Compute unique columns in order of discovery.
23859 function inferColumns(rows) {
23860   var columnSet = Object.create(null),
23861       columns = [];
23862
23863   rows.forEach(function(row) {
23864     for (var column in row) {
23865       if (!(column in columnSet)) {
23866         columns.push(columnSet[column] = column);
23867       }
23868     }
23869   });
23870
23871   return columns;
23872 }
23873
23874 var dsv = function(delimiter) {
23875   var reFormat = new RegExp("[\"" + delimiter + "\n]"),
23876       delimiterCode = delimiter.charCodeAt(0);
23877
23878   function parse(text, f) {
23879     var convert, columns, rows = parseRows(text, function(row, i) {
23880       if (convert) return convert(row, i - 1);
23881       columns = row, convert = f ? customConverter(row, f) : objectConverter(row);
23882     });
23883     rows.columns = columns;
23884     return rows;
23885   }
23886
23887   function parseRows(text, f) {
23888     var EOL = {}, // sentinel value for end-of-line
23889         EOF = {}, // sentinel value for end-of-file
23890         rows = [], // output rows
23891         N = text.length,
23892         I = 0, // current character index
23893         n = 0, // the current line number
23894         t, // the current token
23895         eol; // is the current token followed by EOL?
23896
23897     function token() {
23898       if (I >= N) return EOF; // special case: end of file
23899       if (eol) return eol = false, EOL; // special case: end of line
23900
23901       // special case: quotes
23902       var j = I, c;
23903       if (text.charCodeAt(j) === 34) {
23904         var i = j;
23905         while (i++ < N) {
23906           if (text.charCodeAt(i) === 34) {
23907             if (text.charCodeAt(i + 1) !== 34) break;
23908             ++i;
23909           }
23910         }
23911         I = i + 2;
23912         c = text.charCodeAt(i + 1);
23913         if (c === 13) {
23914           eol = true;
23915           if (text.charCodeAt(i + 2) === 10) ++I;
23916         } else if (c === 10) {
23917           eol = true;
23918         }
23919         return text.slice(j + 1, i).replace(/""/g, "\"");
23920       }
23921
23922       // common case: find next delimiter or newline
23923       while (I < N) {
23924         var k = 1;
23925         c = text.charCodeAt(I++);
23926         if (c === 10) eol = true; // \n
23927         else if (c === 13) { eol = true; if (text.charCodeAt(I) === 10) ++I, ++k; } // \r|\r\n
23928         else if (c !== delimiterCode) continue;
23929         return text.slice(j, I - k);
23930       }
23931
23932       // special case: last token before EOF
23933       return text.slice(j);
23934     }
23935
23936     while ((t = token()) !== EOF) {
23937       var a = [];
23938       while (t !== EOL && t !== EOF) {
23939         a.push(t);
23940         t = token();
23941       }
23942       if (f && (a = f(a, n++)) == null) continue;
23943       rows.push(a);
23944     }
23945
23946     return rows;
23947   }
23948
23949   function format(rows, columns) {
23950     if (columns == null) columns = inferColumns(rows);
23951     return [columns.map(formatValue).join(delimiter)].concat(rows.map(function(row) {
23952       return columns.map(function(column) {
23953         return formatValue(row[column]);
23954       }).join(delimiter);
23955     })).join("\n");
23956   }
23957
23958   function formatRows(rows) {
23959     return rows.map(formatRow).join("\n");
23960   }
23961
23962   function formatRow(row) {
23963     return row.map(formatValue).join(delimiter);
23964   }
23965
23966   function formatValue(text) {
23967     return text == null ? ""
23968         : reFormat.test(text += "") ? "\"" + text.replace(/\"/g, "\"\"") + "\""
23969         : text;
23970   }
23971
23972   return {
23973     parse: parse,
23974     parseRows: parseRows,
23975     format: format,
23976     formatRows: formatRows
23977   };
23978 };
23979
23980 var csv = dsv(",");
23981
23982 var csvParse = csv.parse;
23983 var csvParseRows = csv.parseRows;
23984 var csvFormat = csv.format;
23985 var csvFormatRows = csv.formatRows;
23986
23987 var tsv = dsv("\t");
23988
23989 var tsvParse = tsv.parse;
23990 var tsvParseRows = tsv.parseRows;
23991 var tsvFormat = tsv.format;
23992 var tsvFormatRows = tsv.formatRows;
23993
23994 var request = function(url, callback) {
23995   var request,
23996       event = dispatch("beforesend", "progress", "load", "error"),
23997       mimeType,
23998       headers = map$1(),
23999       xhr = new XMLHttpRequest,
24000       user = null,
24001       password = null,
24002       response,
24003       responseType,
24004       timeout = 0;
24005
24006   // If IE does not support CORS, use XDomainRequest.
24007   if (typeof XDomainRequest !== "undefined"
24008       && !("withCredentials" in xhr)
24009       && /^(http(s)?:)?\/\//.test(url)) xhr = new XDomainRequest;
24010
24011   "onload" in xhr
24012       ? xhr.onload = xhr.onerror = xhr.ontimeout = respond
24013       : xhr.onreadystatechange = function(o) { xhr.readyState > 3 && respond(o); };
24014
24015   function respond(o) {
24016     var status = xhr.status, result;
24017     if (!status && hasResponse(xhr)
24018         || status >= 200 && status < 300
24019         || status === 304) {
24020       if (response) {
24021         try {
24022           result = response.call(request, xhr);
24023         } catch (e) {
24024           event.call("error", request, e);
24025           return;
24026         }
24027       } else {
24028         result = xhr;
24029       }
24030       event.call("load", request, result);
24031     } else {
24032       event.call("error", request, o);
24033     }
24034   }
24035
24036   xhr.onprogress = function(e) {
24037     event.call("progress", request, e);
24038   };
24039
24040   request = {
24041     header: function(name, value) {
24042       name = (name + "").toLowerCase();
24043       if (arguments.length < 2) return headers.get(name);
24044       if (value == null) headers.remove(name);
24045       else headers.set(name, value + "");
24046       return request;
24047     },
24048
24049     // If mimeType is non-null and no Accept header is set, a default is used.
24050     mimeType: function(value) {
24051       if (!arguments.length) return mimeType;
24052       mimeType = value == null ? null : value + "";
24053       return request;
24054     },
24055
24056     // Specifies what type the response value should take;
24057     // for instance, arraybuffer, blob, document, or text.
24058     responseType: function(value) {
24059       if (!arguments.length) return responseType;
24060       responseType = value;
24061       return request;
24062     },
24063
24064     timeout: function(value) {
24065       if (!arguments.length) return timeout;
24066       timeout = +value;
24067       return request;
24068     },
24069
24070     user: function(value) {
24071       return arguments.length < 1 ? user : (user = value == null ? null : value + "", request);
24072     },
24073
24074     password: function(value) {
24075       return arguments.length < 1 ? password : (password = value == null ? null : value + "", request);
24076     },
24077
24078     // Specify how to convert the response content to a specific type;
24079     // changes the callback value on "load" events.
24080     response: function(value) {
24081       response = value;
24082       return request;
24083     },
24084
24085     // Alias for send("GET", …).
24086     get: function(data, callback) {
24087       return request.send("GET", data, callback);
24088     },
24089
24090     // Alias for send("POST", …).
24091     post: function(data, callback) {
24092       return request.send("POST", data, callback);
24093     },
24094
24095     // If callback is non-null, it will be used for error and load events.
24096     send: function(method, data, callback) {
24097       xhr.open(method, url, true, user, password);
24098       if (mimeType != null && !headers.has("accept")) headers.set("accept", mimeType + ",*/*");
24099       if (xhr.setRequestHeader) headers.each(function(value, name) { xhr.setRequestHeader(name, value); });
24100       if (mimeType != null && xhr.overrideMimeType) xhr.overrideMimeType(mimeType);
24101       if (responseType != null) xhr.responseType = responseType;
24102       if (timeout > 0) xhr.timeout = timeout;
24103       if (callback == null && typeof data === "function") callback = data, data = null;
24104       if (callback != null && callback.length === 1) callback = fixCallback(callback);
24105       if (callback != null) request.on("error", callback).on("load", function(xhr) { callback(null, xhr); });
24106       event.call("beforesend", request, xhr);
24107       xhr.send(data == null ? null : data);
24108       return request;
24109     },
24110
24111     abort: function() {
24112       xhr.abort();
24113       return request;
24114     },
24115
24116     on: function() {
24117       var value = event.on.apply(event, arguments);
24118       return value === event ? request : value;
24119     }
24120   };
24121
24122   if (callback != null) {
24123     if (typeof callback !== "function") throw new Error("invalid callback: " + callback);
24124     return request.get(callback);
24125   }
24126
24127   return request;
24128 };
24129
24130 function fixCallback(callback) {
24131   return function(error, xhr) {
24132     callback(error == null ? xhr : null);
24133   };
24134 }
24135
24136 function hasResponse(xhr) {
24137   var type = xhr.responseType;
24138   return type && type !== "text"
24139       ? xhr.response // null on error
24140       : xhr.responseText; // "" on error
24141 }
24142
24143 var type$2 = function(defaultMimeType, response) {
24144   return function(url, callback) {
24145     var r = request(url).mimeType(defaultMimeType).response(response);
24146     if (callback != null) {
24147       if (typeof callback !== "function") throw new Error("invalid callback: " + callback);
24148       return r.get(callback);
24149     }
24150     return r;
24151   };
24152 };
24153
24154 var html = type$2("text/html", function(xhr) {
24155   return document.createRange().createContextualFragment(xhr.responseText);
24156 });
24157
24158 var json = type$2("application/json", function(xhr) {
24159   return JSON.parse(xhr.responseText);
24160 });
24161
24162 var text = type$2("text/plain", function(xhr) {
24163   return xhr.responseText;
24164 });
24165
24166 var xml = type$2("application/xml", function(xhr) {
24167   var xml = xhr.responseXML;
24168   if (!xml) throw new Error("parse error");
24169   return xml;
24170 });
24171
24172 var dsv$1 = function(defaultMimeType, parse) {
24173   return function(url, row, callback) {
24174     if (arguments.length < 3) callback = row, row = null;
24175     var r = request(url).mimeType(defaultMimeType);
24176     r.row = function(_) { return arguments.length ? r.response(responseOf(parse, row = _)) : row; };
24177     r.row(row);
24178     return callback ? r.get(callback) : r;
24179   };
24180 };
24181
24182 function responseOf(parse, row) {
24183   return function(request$$1) {
24184     return parse(request$$1.responseText, row);
24185   };
24186 }
24187
24188 var csv$1 = dsv$1("text/csv", csvParse);
24189
24190 var tsv$1 = dsv$1("text/tab-separated-values", tsvParse);
24191
24192 var frame = 0;
24193 var timeout = 0;
24194 var interval = 0;
24195 var pokeDelay = 1000;
24196 var taskHead;
24197 var taskTail;
24198 var clockLast = 0;
24199 var clockNow = 0;
24200 var clockSkew = 0;
24201 var clock = typeof performance === "object" && performance.now ? performance : Date;
24202 var setFrame = typeof requestAnimationFrame === "function" ? requestAnimationFrame : function(f) { setTimeout(f, 17); };
24203
24204 function now() {
24205   return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew);
24206 }
24207
24208 function clearNow() {
24209   clockNow = 0;
24210 }
24211
24212 function Timer() {
24213   this._call =
24214   this._time =
24215   this._next = null;
24216 }
24217
24218 Timer.prototype = timer.prototype = {
24219   constructor: Timer,
24220   restart: function(callback, delay, time) {
24221     if (typeof callback !== "function") throw new TypeError("callback is not a function");
24222     time = (time == null ? now() : +time) + (delay == null ? 0 : +delay);
24223     if (!this._next && taskTail !== this) {
24224       if (taskTail) taskTail._next = this;
24225       else taskHead = this;
24226       taskTail = this;
24227     }
24228     this._call = callback;
24229     this._time = time;
24230     sleep();
24231   },
24232   stop: function() {
24233     if (this._call) {
24234       this._call = null;
24235       this._time = Infinity;
24236       sleep();
24237     }
24238   }
24239 };
24240
24241 function timer(callback, delay, time) {
24242   var t = new Timer;
24243   t.restart(callback, delay, time);
24244   return t;
24245 }
24246
24247 function timerFlush() {
24248   now(); // Get the current time, if not already set.
24249   ++frame; // Pretend we’ve set an alarm, if we haven’t already.
24250   var t = taskHead, e;
24251   while (t) {
24252     if ((e = clockNow - t._time) >= 0) t._call.call(null, e);
24253     t = t._next;
24254   }
24255   --frame;
24256 }
24257
24258 function wake() {
24259   clockNow = (clockLast = clock.now()) + clockSkew;
24260   frame = timeout = 0;
24261   try {
24262     timerFlush();
24263   } finally {
24264     frame = 0;
24265     nap();
24266     clockNow = 0;
24267   }
24268 }
24269
24270 function poke$1() {
24271   var now = clock.now(), delay = now - clockLast;
24272   if (delay > pokeDelay) clockSkew -= delay, clockLast = now;
24273 }
24274
24275 function nap() {
24276   var t0, t1 = taskHead, t2, time = Infinity;
24277   while (t1) {
24278     if (t1._call) {
24279       if (time > t1._time) time = t1._time;
24280       t0 = t1, t1 = t1._next;
24281     } else {
24282       t2 = t1._next, t1._next = null;
24283       t1 = t0 ? t0._next = t2 : taskHead = t2;
24284     }
24285   }
24286   taskTail = t0;
24287   sleep(time);
24288 }
24289
24290 function sleep(time) {
24291   if (frame) return; // Soonest alarm already set, or will be.
24292   if (timeout) timeout = clearTimeout(timeout);
24293   var delay = time - clockNow;
24294   if (delay > 24) {
24295     if (time < Infinity) timeout = setTimeout(wake, delay);
24296     if (interval) interval = clearInterval(interval);
24297   } else {
24298     if (!interval) interval = setInterval(poke$1, pokeDelay);
24299     frame = 1, setFrame(wake);
24300   }
24301 }
24302
24303 var timeout$1 = function(callback, delay, time) {
24304   var t = new Timer;
24305   delay = delay == null ? 0 : +delay;
24306   t.restart(function(elapsed) {
24307     t.stop();
24308     callback(elapsed + delay);
24309   }, delay, time);
24310   return t;
24311 };
24312
24313 var interval$1 = function(callback, delay, time) {
24314   var t = new Timer, total = delay;
24315   if (delay == null) return t.restart(callback, delay, time), t;
24316   delay = +delay, time = time == null ? now() : +time;
24317   t.restart(function tick(elapsed) {
24318     elapsed += total;
24319     t.restart(tick, total += delay, time);
24320     callback(elapsed);
24321   }, delay, time);
24322   return t;
24323 };
24324
24325 var t0$1 = new Date;
24326 var t1$1 = new Date;
24327
24328 function newInterval(floori, offseti, count, field) {
24329
24330   function interval(date) {
24331     return floori(date = new Date(+date)), date;
24332   }
24333
24334   interval.floor = interval;
24335
24336   interval.ceil = function(date) {
24337     return floori(date = new Date(date - 1)), offseti(date, 1), floori(date), date;
24338   };
24339
24340   interval.round = function(date) {
24341     var d0 = interval(date),
24342         d1 = interval.ceil(date);
24343     return date - d0 < d1 - date ? d0 : d1;
24344   };
24345
24346   interval.offset = function(date, step) {
24347     return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date;
24348   };
24349
24350   interval.range = function(start, stop, step) {
24351     var range = [];
24352     start = interval.ceil(start);
24353     step = step == null ? 1 : Math.floor(step);
24354     if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date
24355     do range.push(new Date(+start)); while (offseti(start, step), floori(start), start < stop)
24356     return range;
24357   };
24358
24359   interval.filter = function(test) {
24360     return newInterval(function(date) {
24361       if (date >= date) while (floori(date), !test(date)) date.setTime(date - 1);
24362     }, function(date, step) {
24363       if (date >= date) while (--step >= 0) while (offseti(date, 1), !test(date)) {} // eslint-disable-line no-empty
24364     });
24365   };
24366
24367   if (count) {
24368     interval.count = function(start, end) {
24369       t0$1.setTime(+start), t1$1.setTime(+end);
24370       floori(t0$1), floori(t1$1);
24371       return Math.floor(count(t0$1, t1$1));
24372     };
24373
24374     interval.every = function(step) {
24375       step = Math.floor(step);
24376       return !isFinite(step) || !(step > 0) ? null
24377           : !(step > 1) ? interval
24378           : interval.filter(field
24379               ? function(d) { return field(d) % step === 0; }
24380               : function(d) { return interval.count(0, d) % step === 0; });
24381     };
24382   }
24383
24384   return interval;
24385 }
24386
24387 var millisecond = newInterval(function() {
24388   // noop
24389 }, function(date, step) {
24390   date.setTime(+date + step);
24391 }, function(start, end) {
24392   return end - start;
24393 });
24394
24395 // An optimized implementation for this simple case.
24396 millisecond.every = function(k) {
24397   k = Math.floor(k);
24398   if (!isFinite(k) || !(k > 0)) return null;
24399   if (!(k > 1)) return millisecond;
24400   return newInterval(function(date) {
24401     date.setTime(Math.floor(date / k) * k);
24402   }, function(date, step) {
24403     date.setTime(+date + step * k);
24404   }, function(start, end) {
24405     return (end - start) / k;
24406   });
24407 };
24408
24409 var milliseconds = millisecond.range;
24410
24411 var durationSecond = 1e3;
24412 var durationMinute = 6e4;
24413 var durationHour = 36e5;
24414 var durationDay = 864e5;
24415 var durationWeek = 6048e5;
24416
24417 var second = newInterval(function(date) {
24418   date.setTime(Math.floor(date / durationSecond) * durationSecond);
24419 }, function(date, step) {
24420   date.setTime(+date + step * durationSecond);
24421 }, function(start, end) {
24422   return (end - start) / durationSecond;
24423 }, function(date) {
24424   return date.getUTCSeconds();
24425 });
24426
24427 var seconds = second.range;
24428
24429 var minute = newInterval(function(date) {
24430   date.setTime(Math.floor(date / durationMinute) * durationMinute);
24431 }, function(date, step) {
24432   date.setTime(+date + step * durationMinute);
24433 }, function(start, end) {
24434   return (end - start) / durationMinute;
24435 }, function(date) {
24436   return date.getMinutes();
24437 });
24438
24439 var minutes = minute.range;
24440
24441 var hour = newInterval(function(date) {
24442   var offset = date.getTimezoneOffset() * durationMinute % durationHour;
24443   if (offset < 0) offset += durationHour;
24444   date.setTime(Math.floor((+date - offset) / durationHour) * durationHour + offset);
24445 }, function(date, step) {
24446   date.setTime(+date + step * durationHour);
24447 }, function(start, end) {
24448   return (end - start) / durationHour;
24449 }, function(date) {
24450   return date.getHours();
24451 });
24452
24453 var hours = hour.range;
24454
24455 var day = newInterval(function(date) {
24456   date.setHours(0, 0, 0, 0);
24457 }, function(date, step) {
24458   date.setDate(date.getDate() + step);
24459 }, function(start, end) {
24460   return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute) / durationDay;
24461 }, function(date) {
24462   return date.getDate() - 1;
24463 });
24464
24465 var days = day.range;
24466
24467 function weekday(i) {
24468   return newInterval(function(date) {
24469     date.setDate(date.getDate() - (date.getDay() + 7 - i) % 7);
24470     date.setHours(0, 0, 0, 0);
24471   }, function(date, step) {
24472     date.setDate(date.getDate() + step * 7);
24473   }, function(start, end) {
24474     return (end - start - (end.getTimezoneOffset() - start.getTimezoneOffset()) * durationMinute) / durationWeek;
24475   });
24476 }
24477
24478 var sunday = weekday(0);
24479 var monday = weekday(1);
24480 var tuesday = weekday(2);
24481 var wednesday = weekday(3);
24482 var thursday = weekday(4);
24483 var friday = weekday(5);
24484 var saturday = weekday(6);
24485
24486 var sundays = sunday.range;
24487 var mondays = monday.range;
24488 var tuesdays = tuesday.range;
24489 var wednesdays = wednesday.range;
24490 var thursdays = thursday.range;
24491 var fridays = friday.range;
24492 var saturdays = saturday.range;
24493
24494 var month = newInterval(function(date) {
24495   date.setDate(1);
24496   date.setHours(0, 0, 0, 0);
24497 }, function(date, step) {
24498   date.setMonth(date.getMonth() + step);
24499 }, function(start, end) {
24500   return end.getMonth() - start.getMonth() + (end.getFullYear() - start.getFullYear()) * 12;
24501 }, function(date) {
24502   return date.getMonth();
24503 });
24504
24505 var months = month.range;
24506
24507 var year = newInterval(function(date) {
24508   date.setMonth(0, 1);
24509   date.setHours(0, 0, 0, 0);
24510 }, function(date, step) {
24511   date.setFullYear(date.getFullYear() + step);
24512 }, function(start, end) {
24513   return end.getFullYear() - start.getFullYear();
24514 }, function(date) {
24515   return date.getFullYear();
24516 });
24517
24518 // An optimized implementation for this simple case.
24519 year.every = function(k) {
24520   return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) {
24521     date.setFullYear(Math.floor(date.getFullYear() / k) * k);
24522     date.setMonth(0, 1);
24523     date.setHours(0, 0, 0, 0);
24524   }, function(date, step) {
24525     date.setFullYear(date.getFullYear() + step * k);
24526   });
24527 };
24528
24529 var years = year.range;
24530
24531 var utcMinute = newInterval(function(date) {
24532   date.setUTCSeconds(0, 0);
24533 }, function(date, step) {
24534   date.setTime(+date + step * durationMinute);
24535 }, function(start, end) {
24536   return (end - start) / durationMinute;
24537 }, function(date) {
24538   return date.getUTCMinutes();
24539 });
24540
24541 var utcMinutes = utcMinute.range;
24542
24543 var utcHour = newInterval(function(date) {
24544   date.setUTCMinutes(0, 0, 0);
24545 }, function(date, step) {
24546   date.setTime(+date + step * durationHour);
24547 }, function(start, end) {
24548   return (end - start) / durationHour;
24549 }, function(date) {
24550   return date.getUTCHours();
24551 });
24552
24553 var utcHours = utcHour.range;
24554
24555 var utcDay = newInterval(function(date) {
24556   date.setUTCHours(0, 0, 0, 0);
24557 }, function(date, step) {
24558   date.setUTCDate(date.getUTCDate() + step);
24559 }, function(start, end) {
24560   return (end - start) / durationDay;
24561 }, function(date) {
24562   return date.getUTCDate() - 1;
24563 });
24564
24565 var utcDays = utcDay.range;
24566
24567 function utcWeekday(i) {
24568   return newInterval(function(date) {
24569     date.setUTCDate(date.getUTCDate() - (date.getUTCDay() + 7 - i) % 7);
24570     date.setUTCHours(0, 0, 0, 0);
24571   }, function(date, step) {
24572     date.setUTCDate(date.getUTCDate() + step * 7);
24573   }, function(start, end) {
24574     return (end - start) / durationWeek;
24575   });
24576 }
24577
24578 var utcSunday = utcWeekday(0);
24579 var utcMonday = utcWeekday(1);
24580 var utcTuesday = utcWeekday(2);
24581 var utcWednesday = utcWeekday(3);
24582 var utcThursday = utcWeekday(4);
24583 var utcFriday = utcWeekday(5);
24584 var utcSaturday = utcWeekday(6);
24585
24586 var utcSundays = utcSunday.range;
24587 var utcMondays = utcMonday.range;
24588 var utcTuesdays = utcTuesday.range;
24589 var utcWednesdays = utcWednesday.range;
24590 var utcThursdays = utcThursday.range;
24591 var utcFridays = utcFriday.range;
24592 var utcSaturdays = utcSaturday.range;
24593
24594 var utcMonth = newInterval(function(date) {
24595   date.setUTCDate(1);
24596   date.setUTCHours(0, 0, 0, 0);
24597 }, function(date, step) {
24598   date.setUTCMonth(date.getUTCMonth() + step);
24599 }, function(start, end) {
24600   return end.getUTCMonth() - start.getUTCMonth() + (end.getUTCFullYear() - start.getUTCFullYear()) * 12;
24601 }, function(date) {
24602   return date.getUTCMonth();
24603 });
24604
24605 var utcMonths = utcMonth.range;
24606
24607 var utcYear = newInterval(function(date) {
24608   date.setUTCMonth(0, 1);
24609   date.setUTCHours(0, 0, 0, 0);
24610 }, function(date, step) {
24611   date.setUTCFullYear(date.getUTCFullYear() + step);
24612 }, function(start, end) {
24613   return end.getUTCFullYear() - start.getUTCFullYear();
24614 }, function(date) {
24615   return date.getUTCFullYear();
24616 });
24617
24618 // An optimized implementation for this simple case.
24619 utcYear.every = function(k) {
24620   return !isFinite(k = Math.floor(k)) || !(k > 0) ? null : newInterval(function(date) {
24621     date.setUTCFullYear(Math.floor(date.getUTCFullYear() / k) * k);
24622     date.setUTCMonth(0, 1);
24623     date.setUTCHours(0, 0, 0, 0);
24624   }, function(date, step) {
24625     date.setUTCFullYear(date.getUTCFullYear() + step * k);
24626   });
24627 };
24628
24629 var utcYears = utcYear.range;
24630
24631 // Computes the decimal coefficient and exponent of the specified number x with
24632 // significant digits p, where x is positive and p is in [1, 21] or undefined.
24633 // For example, formatDecimal(1.23) returns ["123", 0].
24634 var formatDecimal = function(x, p) {
24635   if ((i = (x = p ? x.toExponential(p - 1) : x.toExponential()).indexOf("e")) < 0) return null; // NaN, ±Infinity
24636   var i, coefficient = x.slice(0, i);
24637
24638   // The string returned by toExponential either has the form \d\.\d+e[-+]\d+
24639   // (e.g., 1.2e+3) or the form \de[-+]\d+ (e.g., 1e+3).
24640   return [
24641     coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,
24642     +x.slice(i + 1)
24643   ];
24644 };
24645
24646 var exponent$1 = function(x) {
24647   return x = formatDecimal(Math.abs(x)), x ? x[1] : NaN;
24648 };
24649
24650 var formatGroup = function(grouping, thousands) {
24651   return function(value, width) {
24652     var i = value.length,
24653         t = [],
24654         j = 0,
24655         g = grouping[0],
24656         length = 0;
24657
24658     while (i > 0 && g > 0) {
24659       if (length + g + 1 > width) g = Math.max(1, width - length);
24660       t.push(value.substring(i -= g, i + g));
24661       if ((length += g + 1) > width) break;
24662       g = grouping[j = (j + 1) % grouping.length];
24663     }
24664
24665     return t.reverse().join(thousands);
24666   };
24667 };
24668
24669 var formatDefault = function(x, p) {
24670   x = x.toPrecision(p);
24671
24672   out: for (var n = x.length, i = 1, i0 = -1, i1; i < n; ++i) {
24673     switch (x[i]) {
24674       case ".": i0 = i1 = i; break;
24675       case "0": if (i0 === 0) i0 = i; i1 = i; break;
24676       case "e": break out;
24677       default: if (i0 > 0) i0 = 0; break;
24678     }
24679   }
24680
24681   return i0 > 0 ? x.slice(0, i0) + x.slice(i1 + 1) : x;
24682 };
24683
24684 var prefixExponent;
24685
24686 var formatPrefixAuto = function(x, p) {
24687   var d = formatDecimal(x, p);
24688   if (!d) return x + "";
24689   var coefficient = d[0],
24690       exponent = d[1],
24691       i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1,
24692       n = coefficient.length;
24693   return i === n ? coefficient
24694       : i > n ? coefficient + new Array(i - n + 1).join("0")
24695       : i > 0 ? coefficient.slice(0, i) + "." + coefficient.slice(i)
24696       : "0." + new Array(1 - i).join("0") + formatDecimal(x, Math.max(0, p + i - 1))[0]; // less than 1y!
24697 };
24698
24699 var formatRounded = function(x, p) {
24700   var d = formatDecimal(x, p);
24701   if (!d) return x + "";
24702   var coefficient = d[0],
24703       exponent = d[1];
24704   return exponent < 0 ? "0." + new Array(-exponent).join("0") + coefficient
24705       : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + "." + coefficient.slice(exponent + 1)
24706       : coefficient + new Array(exponent - coefficient.length + 2).join("0");
24707 };
24708
24709 var formatTypes = {
24710   "": formatDefault,
24711   "%": function(x, p) { return (x * 100).toFixed(p); },
24712   "b": function(x) { return Math.round(x).toString(2); },
24713   "c": function(x) { return x + ""; },
24714   "d": function(x) { return Math.round(x).toString(10); },
24715   "e": function(x, p) { return x.toExponential(p); },
24716   "f": function(x, p) { return x.toFixed(p); },
24717   "g": function(x, p) { return x.toPrecision(p); },
24718   "o": function(x) { return Math.round(x).toString(8); },
24719   "p": function(x, p) { return formatRounded(x * 100, p); },
24720   "r": formatRounded,
24721   "s": formatPrefixAuto,
24722   "X": function(x) { return Math.round(x).toString(16).toUpperCase(); },
24723   "x": function(x) { return Math.round(x).toString(16); }
24724 };
24725
24726 // [[fill]align][sign][symbol][0][width][,][.precision][type]
24727 var re = /^(?:(.)?([<>=^]))?([+\-\( ])?([$#])?(0)?(\d+)?(,)?(\.\d+)?([a-z%])?$/i;
24728
24729 var formatSpecifier = function(specifier) {
24730   return new FormatSpecifier(specifier);
24731 };
24732
24733 function FormatSpecifier(specifier) {
24734   if (!(match = re.exec(specifier))) throw new Error("invalid format: " + specifier);
24735
24736   var match,
24737       fill = match[1] || " ",
24738       align = match[2] || ">",
24739       sign = match[3] || "-",
24740       symbol = match[4] || "",
24741       zero = !!match[5],
24742       width = match[6] && +match[6],
24743       comma = !!match[7],
24744       precision = match[8] && +match[8].slice(1),
24745       type = match[9] || "";
24746
24747   // The "n" type is an alias for ",g".
24748   if (type === "n") comma = true, type = "g";
24749
24750   // Map invalid types to the default format.
24751   else if (!formatTypes[type]) type = "";
24752
24753   // If zero fill is specified, padding goes after sign and before digits.
24754   if (zero || (fill === "0" && align === "=")) zero = true, fill = "0", align = "=";
24755
24756   this.fill = fill;
24757   this.align = align;
24758   this.sign = sign;
24759   this.symbol = symbol;
24760   this.zero = zero;
24761   this.width = width;
24762   this.comma = comma;
24763   this.precision = precision;
24764   this.type = type;
24765 }
24766
24767 FormatSpecifier.prototype.toString = function() {
24768   return this.fill
24769       + this.align
24770       + this.sign
24771       + this.symbol
24772       + (this.zero ? "0" : "")
24773       + (this.width == null ? "" : Math.max(1, this.width | 0))
24774       + (this.comma ? "," : "")
24775       + (this.precision == null ? "" : "." + Math.max(0, this.precision | 0))
24776       + this.type;
24777 };
24778
24779 var prefixes = ["y","z","a","f","p","n","µ","m","","k","M","G","T","P","E","Z","Y"];
24780
24781 function identity$3(x) {
24782   return x;
24783 }
24784
24785 var formatLocale = function(locale) {
24786   var group = locale.grouping && locale.thousands ? formatGroup(locale.grouping, locale.thousands) : identity$3,
24787       currency = locale.currency,
24788       decimal = locale.decimal;
24789
24790   function newFormat(specifier) {
24791     specifier = formatSpecifier(specifier);
24792
24793     var fill = specifier.fill,
24794         align = specifier.align,
24795         sign = specifier.sign,
24796         symbol = specifier.symbol,
24797         zero = specifier.zero,
24798         width = specifier.width,
24799         comma = specifier.comma,
24800         precision = specifier.precision,
24801         type = specifier.type;
24802
24803     // Compute the prefix and suffix.
24804     // For SI-prefix, the suffix is lazily computed.
24805     var prefix = symbol === "$" ? currency[0] : symbol === "#" && /[boxX]/.test(type) ? "0" + type.toLowerCase() : "",
24806         suffix = symbol === "$" ? currency[1] : /[%p]/.test(type) ? "%" : "";
24807
24808     // What format function should we use?
24809     // Is this an integer type?
24810     // Can this type generate exponential notation?
24811     var formatType = formatTypes[type],
24812         maybeSuffix = !type || /[defgprs%]/.test(type);
24813
24814     // Set the default precision if not specified,
24815     // or clamp the specified precision to the supported range.
24816     // For significant precision, it must be in [1, 21].
24817     // For fixed precision, it must be in [0, 20].
24818     precision = precision == null ? (type ? 6 : 12)
24819         : /[gprs]/.test(type) ? Math.max(1, Math.min(21, precision))
24820         : Math.max(0, Math.min(20, precision));
24821
24822     function format(value) {
24823       var valuePrefix = prefix,
24824           valueSuffix = suffix,
24825           i, n, c;
24826
24827       if (type === "c") {
24828         valueSuffix = formatType(value) + valueSuffix;
24829         value = "";
24830       } else {
24831         value = +value;
24832
24833         // Convert negative to positive, and compute the prefix.
24834         // Note that -0 is not less than 0, but 1 / -0 is!
24835         var valueNegative = (value < 0 || 1 / value < 0) && (value *= -1, true);
24836
24837         // Perform the initial formatting.
24838         value = formatType(value, precision);
24839
24840         // If the original value was negative, it may be rounded to zero during
24841         // formatting; treat this as (positive) zero.
24842         if (valueNegative) {
24843           i = -1, n = value.length;
24844           valueNegative = false;
24845           while (++i < n) {
24846             if (c = value.charCodeAt(i), (48 < c && c < 58)
24847                 || (type === "x" && 96 < c && c < 103)
24848                 || (type === "X" && 64 < c && c < 71)) {
24849               valueNegative = true;
24850               break;
24851             }
24852           }
24853         }
24854
24855         // Compute the prefix and suffix.
24856         valuePrefix = (valueNegative ? (sign === "(" ? sign : "-") : sign === "-" || sign === "(" ? "" : sign) + valuePrefix;
24857         valueSuffix = valueSuffix + (type === "s" ? prefixes[8 + prefixExponent / 3] : "") + (valueNegative && sign === "(" ? ")" : "");
24858
24859         // Break the formatted value into the integer “value” part that can be
24860         // grouped, and fractional or exponential “suffix” part that is not.
24861         if (maybeSuffix) {
24862           i = -1, n = value.length;
24863           while (++i < n) {
24864             if (c = value.charCodeAt(i), 48 > c || c > 57) {
24865               valueSuffix = (c === 46 ? decimal + value.slice(i + 1) : value.slice(i)) + valueSuffix;
24866               value = value.slice(0, i);
24867               break;
24868             }
24869           }
24870         }
24871       }
24872
24873       // If the fill character is not "0", grouping is applied before padding.
24874       if (comma && !zero) value = group(value, Infinity);
24875
24876       // Compute the padding.
24877       var length = valuePrefix.length + value.length + valueSuffix.length,
24878           padding = length < width ? new Array(width - length + 1).join(fill) : "";
24879
24880       // If the fill character is "0", grouping is applied after padding.
24881       if (comma && zero) value = group(padding + value, padding.length ? width - valueSuffix.length : Infinity), padding = "";
24882
24883       // Reconstruct the final output based on the desired alignment.
24884       switch (align) {
24885         case "<": return valuePrefix + value + valueSuffix + padding;
24886         case "=": return valuePrefix + padding + value + valueSuffix;
24887         case "^": return padding.slice(0, length = padding.length >> 1) + valuePrefix + value + valueSuffix + padding.slice(length);
24888       }
24889       return padding + valuePrefix + value + valueSuffix;
24890     }
24891
24892     format.toString = function() {
24893       return specifier + "";
24894     };
24895
24896     return format;
24897   }
24898
24899   function formatPrefix(specifier, value) {
24900     var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = "f", specifier)),
24901         e = Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3,
24902         k = Math.pow(10, -e),
24903         prefix = prefixes[8 + e / 3];
24904     return function(value) {
24905       return f(k * value) + prefix;
24906     };
24907   }
24908
24909   return {
24910     format: newFormat,
24911     formatPrefix: formatPrefix
24912   };
24913 };
24914
24915 var locale$1;
24916 var format;
24917 var formatPrefix;
24918
24919 defaultLocale({
24920   decimal: ".",
24921   thousands: ",",
24922   grouping: [3],
24923   currency: ["$", ""]
24924 });
24925
24926 function defaultLocale(definition) {
24927   locale$1 = formatLocale(definition);
24928   format = locale$1.format;
24929   formatPrefix = locale$1.formatPrefix;
24930   return locale$1;
24931 }
24932
24933 var precisionFixed = function(step) {
24934   return Math.max(0, -exponent$1(Math.abs(step)));
24935 };
24936
24937 var precisionPrefix = function(step, value) {
24938   return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent$1(value) / 3))) * 3 - exponent$1(Math.abs(step)));
24939 };
24940
24941 var precisionRound = function(step, max) {
24942   step = Math.abs(step), max = Math.abs(max) - step;
24943   return Math.max(0, exponent$1(max) - exponent$1(step)) + 1;
24944 };
24945
24946 function localDate(d) {
24947   if (0 <= d.y && d.y < 100) {
24948     var date = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L);
24949     date.setFullYear(d.y);
24950     return date;
24951   }
24952   return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L);
24953 }
24954
24955 function utcDate(d) {
24956   if (0 <= d.y && d.y < 100) {
24957     var date = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L));
24958     date.setUTCFullYear(d.y);
24959     return date;
24960   }
24961   return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L));
24962 }
24963
24964 function newYear(y) {
24965   return {y: y, m: 0, d: 1, H: 0, M: 0, S: 0, L: 0};
24966 }
24967
24968 function formatLocale$1(locale) {
24969   var locale_dateTime = locale.dateTime,
24970       locale_date = locale.date,
24971       locale_time = locale.time,
24972       locale_periods = locale.periods,
24973       locale_weekdays = locale.days,
24974       locale_shortWeekdays = locale.shortDays,
24975       locale_months = locale.months,
24976       locale_shortMonths = locale.shortMonths;
24977
24978   var periodRe = formatRe(locale_periods),
24979       periodLookup = formatLookup(locale_periods),
24980       weekdayRe = formatRe(locale_weekdays),
24981       weekdayLookup = formatLookup(locale_weekdays),
24982       shortWeekdayRe = formatRe(locale_shortWeekdays),
24983       shortWeekdayLookup = formatLookup(locale_shortWeekdays),
24984       monthRe = formatRe(locale_months),
24985       monthLookup = formatLookup(locale_months),
24986       shortMonthRe = formatRe(locale_shortMonths),
24987       shortMonthLookup = formatLookup(locale_shortMonths);
24988
24989   var formats = {
24990     "a": formatShortWeekday,
24991     "A": formatWeekday,
24992     "b": formatShortMonth,
24993     "B": formatMonth,
24994     "c": null,
24995     "d": formatDayOfMonth,
24996     "e": formatDayOfMonth,
24997     "H": formatHour24,
24998     "I": formatHour12,
24999     "j": formatDayOfYear,
25000     "L": formatMilliseconds,
25001     "m": formatMonthNumber,
25002     "M": formatMinutes,
25003     "p": formatPeriod,
25004     "S": formatSeconds,
25005     "U": formatWeekNumberSunday,
25006     "w": formatWeekdayNumber,
25007     "W": formatWeekNumberMonday,
25008     "x": null,
25009     "X": null,
25010     "y": formatYear,
25011     "Y": formatFullYear,
25012     "Z": formatZone,
25013     "%": formatLiteralPercent
25014   };
25015
25016   var utcFormats = {
25017     "a": formatUTCShortWeekday,
25018     "A": formatUTCWeekday,
25019     "b": formatUTCShortMonth,
25020     "B": formatUTCMonth,
25021     "c": null,
25022     "d": formatUTCDayOfMonth,
25023     "e": formatUTCDayOfMonth,
25024     "H": formatUTCHour24,
25025     "I": formatUTCHour12,
25026     "j": formatUTCDayOfYear,
25027     "L": formatUTCMilliseconds,
25028     "m": formatUTCMonthNumber,
25029     "M": formatUTCMinutes,
25030     "p": formatUTCPeriod,
25031     "S": formatUTCSeconds,
25032     "U": formatUTCWeekNumberSunday,
25033     "w": formatUTCWeekdayNumber,
25034     "W": formatUTCWeekNumberMonday,
25035     "x": null,
25036     "X": null,
25037     "y": formatUTCYear,
25038     "Y": formatUTCFullYear,
25039     "Z": formatUTCZone,
25040     "%": formatLiteralPercent
25041   };
25042
25043   var parses = {
25044     "a": parseShortWeekday,
25045     "A": parseWeekday,
25046     "b": parseShortMonth,
25047     "B": parseMonth,
25048     "c": parseLocaleDateTime,
25049     "d": parseDayOfMonth,
25050     "e": parseDayOfMonth,
25051     "H": parseHour24,
25052     "I": parseHour24,
25053     "j": parseDayOfYear,
25054     "L": parseMilliseconds,
25055     "m": parseMonthNumber,
25056     "M": parseMinutes,
25057     "p": parsePeriod,
25058     "S": parseSeconds,
25059     "U": parseWeekNumberSunday,
25060     "w": parseWeekdayNumber,
25061     "W": parseWeekNumberMonday,
25062     "x": parseLocaleDate,
25063     "X": parseLocaleTime,
25064     "y": parseYear,
25065     "Y": parseFullYear,
25066     "Z": parseZone,
25067     "%": parseLiteralPercent
25068   };
25069
25070   // These recursive directive definitions must be deferred.
25071   formats.x = newFormat(locale_date, formats);
25072   formats.X = newFormat(locale_time, formats);
25073   formats.c = newFormat(locale_dateTime, formats);
25074   utcFormats.x = newFormat(locale_date, utcFormats);
25075   utcFormats.X = newFormat(locale_time, utcFormats);
25076   utcFormats.c = newFormat(locale_dateTime, utcFormats);
25077
25078   function newFormat(specifier, formats) {
25079     return function(date) {
25080       var string = [],
25081           i = -1,
25082           j = 0,
25083           n = specifier.length,
25084           c,
25085           pad,
25086           format;
25087
25088       if (!(date instanceof Date)) date = new Date(+date);
25089
25090       while (++i < n) {
25091         if (specifier.charCodeAt(i) === 37) {
25092           string.push(specifier.slice(j, i));
25093           if ((pad = pads[c = specifier.charAt(++i)]) != null) c = specifier.charAt(++i);
25094           else pad = c === "e" ? " " : "0";
25095           if (format = formats[c]) c = format(date, pad);
25096           string.push(c);
25097           j = i + 1;
25098         }
25099       }
25100
25101       string.push(specifier.slice(j, i));
25102       return string.join("");
25103     };
25104   }
25105
25106   function newParse(specifier, newDate) {
25107     return function(string) {
25108       var d = newYear(1900),
25109           i = parseSpecifier(d, specifier, string += "", 0);
25110       if (i != string.length) return null;
25111
25112       // The am-pm flag is 0 for AM, and 1 for PM.
25113       if ("p" in d) d.H = d.H % 12 + d.p * 12;
25114
25115       // Convert day-of-week and week-of-year to day-of-year.
25116       if ("W" in d || "U" in d) {
25117         if (!("w" in d)) d.w = "W" in d ? 1 : 0;
25118         var day$$1 = "Z" in d ? utcDate(newYear(d.y)).getUTCDay() : newDate(newYear(d.y)).getDay();
25119         d.m = 0;
25120         d.d = "W" in d ? (d.w + 6) % 7 + d.W * 7 - (day$$1 + 5) % 7 : d.w + d.U * 7 - (day$$1 + 6) % 7;
25121       }
25122
25123       // If a time zone is specified, all fields are interpreted as UTC and then
25124       // offset according to the specified time zone.
25125       if ("Z" in d) {
25126         d.H += d.Z / 100 | 0;
25127         d.M += d.Z % 100;
25128         return utcDate(d);
25129       }
25130
25131       // Otherwise, all fields are in local time.
25132       return newDate(d);
25133     };
25134   }
25135
25136   function parseSpecifier(d, specifier, string, j) {
25137     var i = 0,
25138         n = specifier.length,
25139         m = string.length,
25140         c,
25141         parse;
25142
25143     while (i < n) {
25144       if (j >= m) return -1;
25145       c = specifier.charCodeAt(i++);
25146       if (c === 37) {
25147         c = specifier.charAt(i++);
25148         parse = parses[c in pads ? specifier.charAt(i++) : c];
25149         if (!parse || ((j = parse(d, string, j)) < 0)) return -1;
25150       } else if (c != string.charCodeAt(j++)) {
25151         return -1;
25152       }
25153     }
25154
25155     return j;
25156   }
25157
25158   function parsePeriod(d, string, i) {
25159     var n = periodRe.exec(string.slice(i));
25160     return n ? (d.p = periodLookup[n[0].toLowerCase()], i + n[0].length) : -1;
25161   }
25162
25163   function parseShortWeekday(d, string, i) {
25164     var n = shortWeekdayRe.exec(string.slice(i));
25165     return n ? (d.w = shortWeekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
25166   }
25167
25168   function parseWeekday(d, string, i) {
25169     var n = weekdayRe.exec(string.slice(i));
25170     return n ? (d.w = weekdayLookup[n[0].toLowerCase()], i + n[0].length) : -1;
25171   }
25172
25173   function parseShortMonth(d, string, i) {
25174     var n = shortMonthRe.exec(string.slice(i));
25175     return n ? (d.m = shortMonthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
25176   }
25177
25178   function parseMonth(d, string, i) {
25179     var n = monthRe.exec(string.slice(i));
25180     return n ? (d.m = monthLookup[n[0].toLowerCase()], i + n[0].length) : -1;
25181   }
25182
25183   function parseLocaleDateTime(d, string, i) {
25184     return parseSpecifier(d, locale_dateTime, string, i);
25185   }
25186
25187   function parseLocaleDate(d, string, i) {
25188     return parseSpecifier(d, locale_date, string, i);
25189   }
25190
25191   function parseLocaleTime(d, string, i) {
25192     return parseSpecifier(d, locale_time, string, i);
25193   }
25194
25195   function formatShortWeekday(d) {
25196     return locale_shortWeekdays[d.getDay()];
25197   }
25198
25199   function formatWeekday(d) {
25200     return locale_weekdays[d.getDay()];
25201   }
25202
25203   function formatShortMonth(d) {
25204     return locale_shortMonths[d.getMonth()];
25205   }
25206
25207   function formatMonth(d) {
25208     return locale_months[d.getMonth()];
25209   }
25210
25211   function formatPeriod(d) {
25212     return locale_periods[+(d.getHours() >= 12)];
25213   }
25214
25215   function formatUTCShortWeekday(d) {
25216     return locale_shortWeekdays[d.getUTCDay()];
25217   }
25218
25219   function formatUTCWeekday(d) {
25220     return locale_weekdays[d.getUTCDay()];
25221   }
25222
25223   function formatUTCShortMonth(d) {
25224     return locale_shortMonths[d.getUTCMonth()];
25225   }
25226
25227   function formatUTCMonth(d) {
25228     return locale_months[d.getUTCMonth()];
25229   }
25230
25231   function formatUTCPeriod(d) {
25232     return locale_periods[+(d.getUTCHours() >= 12)];
25233   }
25234
25235   return {
25236     format: function(specifier) {
25237       var f = newFormat(specifier += "", formats);
25238       f.toString = function() { return specifier; };
25239       return f;
25240     },
25241     parse: function(specifier) {
25242       var p = newParse(specifier += "", localDate);
25243       p.toString = function() { return specifier; };
25244       return p;
25245     },
25246     utcFormat: function(specifier) {
25247       var f = newFormat(specifier += "", utcFormats);
25248       f.toString = function() { return specifier; };
25249       return f;
25250     },
25251     utcParse: function(specifier) {
25252       var p = newParse(specifier, utcDate);
25253       p.toString = function() { return specifier; };
25254       return p;
25255     }
25256   };
25257 }
25258
25259 var pads = {"-": "", "_": " ", "0": "0"};
25260 var numberRe = /^\s*\d+/;
25261 var percentRe = /^%/;
25262 var requoteRe = /[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g;
25263
25264 function pad(value, fill, width) {
25265   var sign = value < 0 ? "-" : "",
25266       string = (sign ? -value : value) + "",
25267       length = string.length;
25268   return sign + (length < width ? new Array(width - length + 1).join(fill) + string : string);
25269 }
25270
25271 function requote(s) {
25272   return s.replace(requoteRe, "\\$&");
25273 }
25274
25275 function formatRe(names) {
25276   return new RegExp("^(?:" + names.map(requote).join("|") + ")", "i");
25277 }
25278
25279 function formatLookup(names) {
25280   var map = {}, i = -1, n = names.length;
25281   while (++i < n) map[names[i].toLowerCase()] = i;
25282   return map;
25283 }
25284
25285 function parseWeekdayNumber(d, string, i) {
25286   var n = numberRe.exec(string.slice(i, i + 1));
25287   return n ? (d.w = +n[0], i + n[0].length) : -1;
25288 }
25289
25290 function parseWeekNumberSunday(d, string, i) {
25291   var n = numberRe.exec(string.slice(i));
25292   return n ? (d.U = +n[0], i + n[0].length) : -1;
25293 }
25294
25295 function parseWeekNumberMonday(d, string, i) {
25296   var n = numberRe.exec(string.slice(i));
25297   return n ? (d.W = +n[0], i + n[0].length) : -1;
25298 }
25299
25300 function parseFullYear(d, string, i) {
25301   var n = numberRe.exec(string.slice(i, i + 4));
25302   return n ? (d.y = +n[0], i + n[0].length) : -1;
25303 }
25304
25305 function parseYear(d, string, i) {
25306   var n = numberRe.exec(string.slice(i, i + 2));
25307   return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2000), i + n[0].length) : -1;
25308 }
25309
25310 function parseZone(d, string, i) {
25311   var n = /^(Z)|([+-]\d\d)(?:\:?(\d\d))?/.exec(string.slice(i, i + 6));
25312   return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || "00")), i + n[0].length) : -1;
25313 }
25314
25315 function parseMonthNumber(d, string, i) {
25316   var n = numberRe.exec(string.slice(i, i + 2));
25317   return n ? (d.m = n[0] - 1, i + n[0].length) : -1;
25318 }
25319
25320 function parseDayOfMonth(d, string, i) {
25321   var n = numberRe.exec(string.slice(i, i + 2));
25322   return n ? (d.d = +n[0], i + n[0].length) : -1;
25323 }
25324
25325 function parseDayOfYear(d, string, i) {
25326   var n = numberRe.exec(string.slice(i, i + 3));
25327   return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1;
25328 }
25329
25330 function parseHour24(d, string, i) {
25331   var n = numberRe.exec(string.slice(i, i + 2));
25332   return n ? (d.H = +n[0], i + n[0].length) : -1;
25333 }
25334
25335 function parseMinutes(d, string, i) {
25336   var n = numberRe.exec(string.slice(i, i + 2));
25337   return n ? (d.M = +n[0], i + n[0].length) : -1;
25338 }
25339
25340 function parseSeconds(d, string, i) {
25341   var n = numberRe.exec(string.slice(i, i + 2));
25342   return n ? (d.S = +n[0], i + n[0].length) : -1;
25343 }
25344
25345 function parseMilliseconds(d, string, i) {
25346   var n = numberRe.exec(string.slice(i, i + 3));
25347   return n ? (d.L = +n[0], i + n[0].length) : -1;
25348 }
25349
25350 function parseLiteralPercent(d, string, i) {
25351   var n = percentRe.exec(string.slice(i, i + 1));
25352   return n ? i + n[0].length : -1;
25353 }
25354
25355 function formatDayOfMonth(d, p) {
25356   return pad(d.getDate(), p, 2);
25357 }
25358
25359 function formatHour24(d, p) {
25360   return pad(d.getHours(), p, 2);
25361 }
25362
25363 function formatHour12(d, p) {
25364   return pad(d.getHours() % 12 || 12, p, 2);
25365 }
25366
25367 function formatDayOfYear(d, p) {
25368   return pad(1 + day.count(year(d), d), p, 3);
25369 }
25370
25371 function formatMilliseconds(d, p) {
25372   return pad(d.getMilliseconds(), p, 3);
25373 }
25374
25375 function formatMonthNumber(d, p) {
25376   return pad(d.getMonth() + 1, p, 2);
25377 }
25378
25379 function formatMinutes(d, p) {
25380   return pad(d.getMinutes(), p, 2);
25381 }
25382
25383 function formatSeconds(d, p) {
25384   return pad(d.getSeconds(), p, 2);
25385 }
25386
25387 function formatWeekNumberSunday(d, p) {
25388   return pad(sunday.count(year(d), d), p, 2);
25389 }
25390
25391 function formatWeekdayNumber(d) {
25392   return d.getDay();
25393 }
25394
25395 function formatWeekNumberMonday(d, p) {
25396   return pad(monday.count(year(d), d), p, 2);
25397 }
25398
25399 function formatYear(d, p) {
25400   return pad(d.getFullYear() % 100, p, 2);
25401 }
25402
25403 function formatFullYear(d, p) {
25404   return pad(d.getFullYear() % 10000, p, 4);
25405 }
25406
25407 function formatZone(d) {
25408   var z = d.getTimezoneOffset();
25409   return (z > 0 ? "-" : (z *= -1, "+"))
25410       + pad(z / 60 | 0, "0", 2)
25411       + pad(z % 60, "0", 2);
25412 }
25413
25414 function formatUTCDayOfMonth(d, p) {
25415   return pad(d.getUTCDate(), p, 2);
25416 }
25417
25418 function formatUTCHour24(d, p) {
25419   return pad(d.getUTCHours(), p, 2);
25420 }
25421
25422 function formatUTCHour12(d, p) {
25423   return pad(d.getUTCHours() % 12 || 12, p, 2);
25424 }
25425
25426 function formatUTCDayOfYear(d, p) {
25427   return pad(1 + utcDay.count(utcYear(d), d), p, 3);
25428 }
25429
25430 function formatUTCMilliseconds(d, p) {
25431   return pad(d.getUTCMilliseconds(), p, 3);
25432 }
25433
25434 function formatUTCMonthNumber(d, p) {
25435   return pad(d.getUTCMonth() + 1, p, 2);
25436 }
25437
25438 function formatUTCMinutes(d, p) {
25439   return pad(d.getUTCMinutes(), p, 2);
25440 }
25441
25442 function formatUTCSeconds(d, p) {
25443   return pad(d.getUTCSeconds(), p, 2);
25444 }
25445
25446 function formatUTCWeekNumberSunday(d, p) {
25447   return pad(utcSunday.count(utcYear(d), d), p, 2);
25448 }
25449
25450 function formatUTCWeekdayNumber(d) {
25451   return d.getUTCDay();
25452 }
25453
25454 function formatUTCWeekNumberMonday(d, p) {
25455   return pad(utcMonday.count(utcYear(d), d), p, 2);
25456 }
25457
25458 function formatUTCYear(d, p) {
25459   return pad(d.getUTCFullYear() % 100, p, 2);
25460 }
25461
25462 function formatUTCFullYear(d, p) {
25463   return pad(d.getUTCFullYear() % 10000, p, 4);
25464 }
25465
25466 function formatUTCZone() {
25467   return "+0000";
25468 }
25469
25470 function formatLiteralPercent() {
25471   return "%";
25472 }
25473
25474 var locale$2;
25475 var timeFormat;
25476 var timeParse;
25477 var utcFormat;
25478 var utcParse;
25479
25480 defaultLocale$1({
25481   dateTime: "%x, %X",
25482   date: "%-m/%-d/%Y",
25483   time: "%-I:%M:%S %p",
25484   periods: ["AM", "PM"],
25485   days: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
25486   shortDays: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
25487   months: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
25488   shortMonths: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
25489 });
25490
25491 function defaultLocale$1(definition) {
25492   locale$2 = formatLocale$1(definition);
25493   timeFormat = locale$2.format;
25494   timeParse = locale$2.parse;
25495   utcFormat = locale$2.utcFormat;
25496   utcParse = locale$2.utcParse;
25497   return locale$2;
25498 }
25499
25500 var isoSpecifier = "%Y-%m-%dT%H:%M:%S.%LZ";
25501
25502 function formatIsoNative(date) {
25503   return date.toISOString();
25504 }
25505
25506 var formatIso = Date.prototype.toISOString
25507     ? formatIsoNative
25508     : utcFormat(isoSpecifier);
25509
25510 function parseIsoNative(string) {
25511   var date = new Date(string);
25512   return isNaN(date) ? null : date;
25513 }
25514
25515 var parseIso = +new Date("2000-01-01T00:00:00.000Z")
25516     ? parseIsoNative
25517     : utcParse(isoSpecifier);
25518
25519 var array$2 = Array.prototype;
25520
25521 var map$3 = array$2.map;
25522 var slice$3 = array$2.slice;
25523
25524 var implicit = {name: "implicit"};
25525
25526 function ordinal(range) {
25527   var index = map$1(),
25528       domain = [],
25529       unknown = implicit;
25530
25531   range = range == null ? [] : slice$3.call(range);
25532
25533   function scale(d) {
25534     var key = d + "", i = index.get(key);
25535     if (!i) {
25536       if (unknown !== implicit) return unknown;
25537       index.set(key, i = domain.push(d));
25538     }
25539     return range[(i - 1) % range.length];
25540   }
25541
25542   scale.domain = function(_) {
25543     if (!arguments.length) return domain.slice();
25544     domain = [], index = map$1();
25545     var i = -1, n = _.length, d, key;
25546     while (++i < n) if (!index.has(key = (d = _[i]) + "")) index.set(key, domain.push(d));
25547     return scale;
25548   };
25549
25550   scale.range = function(_) {
25551     return arguments.length ? (range = slice$3.call(_), scale) : range.slice();
25552   };
25553
25554   scale.unknown = function(_) {
25555     return arguments.length ? (unknown = _, scale) : unknown;
25556   };
25557
25558   scale.copy = function() {
25559     return ordinal()
25560         .domain(domain)
25561         .range(range)
25562         .unknown(unknown);
25563   };
25564
25565   return scale;
25566 }
25567
25568 function band() {
25569   var scale = ordinal().unknown(undefined),
25570       domain = scale.domain,
25571       ordinalRange = scale.range,
25572       range$$1 = [0, 1],
25573       step,
25574       bandwidth,
25575       round = false,
25576       paddingInner = 0,
25577       paddingOuter = 0,
25578       align = 0.5;
25579
25580   delete scale.unknown;
25581
25582   function rescale() {
25583     var n = domain().length,
25584         reverse = range$$1[1] < range$$1[0],
25585         start = range$$1[reverse - 0],
25586         stop = range$$1[1 - reverse];
25587     step = (stop - start) / Math.max(1, n - paddingInner + paddingOuter * 2);
25588     if (round) step = Math.floor(step);
25589     start += (stop - start - step * (n - paddingInner)) * align;
25590     bandwidth = step * (1 - paddingInner);
25591     if (round) start = Math.round(start), bandwidth = Math.round(bandwidth);
25592     var values = range(n).map(function(i) { return start + step * i; });
25593     return ordinalRange(reverse ? values.reverse() : values);
25594   }
25595
25596   scale.domain = function(_) {
25597     return arguments.length ? (domain(_), rescale()) : domain();
25598   };
25599
25600   scale.range = function(_) {
25601     return arguments.length ? (range$$1 = [+_[0], +_[1]], rescale()) : range$$1.slice();
25602   };
25603
25604   scale.rangeRound = function(_) {
25605     return range$$1 = [+_[0], +_[1]], round = true, rescale();
25606   };
25607
25608   scale.bandwidth = function() {
25609     return bandwidth;
25610   };
25611
25612   scale.step = function() {
25613     return step;
25614   };
25615
25616   scale.round = function(_) {
25617     return arguments.length ? (round = !!_, rescale()) : round;
25618   };
25619
25620   scale.padding = function(_) {
25621     return arguments.length ? (paddingInner = paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingInner;
25622   };
25623
25624   scale.paddingInner = function(_) {
25625     return arguments.length ? (paddingInner = Math.max(0, Math.min(1, _)), rescale()) : paddingInner;
25626   };
25627
25628   scale.paddingOuter = function(_) {
25629     return arguments.length ? (paddingOuter = Math.max(0, Math.min(1, _)), rescale()) : paddingOuter;
25630   };
25631
25632   scale.align = function(_) {
25633     return arguments.length ? (align = Math.max(0, Math.min(1, _)), rescale()) : align;
25634   };
25635
25636   scale.copy = function() {
25637     return band()
25638         .domain(domain())
25639         .range(range$$1)
25640         .round(round)
25641         .paddingInner(paddingInner)
25642         .paddingOuter(paddingOuter)
25643         .align(align);
25644   };
25645
25646   return rescale();
25647 }
25648
25649 function pointish(scale) {
25650   var copy = scale.copy;
25651
25652   scale.padding = scale.paddingOuter;
25653   delete scale.paddingInner;
25654   delete scale.paddingOuter;
25655
25656   scale.copy = function() {
25657     return pointish(copy());
25658   };
25659
25660   return scale;
25661 }
25662
25663 function point$4() {
25664   return pointish(band().paddingInner(1));
25665 }
25666
25667 var constant$4 = function(x) {
25668   return function() {
25669     return x;
25670   };
25671 };
25672
25673 var number$1 = function(x) {
25674   return +x;
25675 };
25676
25677 var unit = [0, 1];
25678
25679 function deinterpolateLinear(a, b) {
25680   return (b -= (a = +a))
25681       ? function(x) { return (x - a) / b; }
25682       : constant$4(b);
25683 }
25684
25685 function deinterpolateClamp(deinterpolate) {
25686   return function(a, b) {
25687     var d = deinterpolate(a = +a, b = +b);
25688     return function(x) { return x <= a ? 0 : x >= b ? 1 : d(x); };
25689   };
25690 }
25691
25692 function reinterpolateClamp(reinterpolate) {
25693   return function(a, b) {
25694     var r = reinterpolate(a = +a, b = +b);
25695     return function(t) { return t <= 0 ? a : t >= 1 ? b : r(t); };
25696   };
25697 }
25698
25699 function bimap(domain, range$$1, deinterpolate, reinterpolate) {
25700   var d0 = domain[0], d1 = domain[1], r0 = range$$1[0], r1 = range$$1[1];
25701   if (d1 < d0) d0 = deinterpolate(d1, d0), r0 = reinterpolate(r1, r0);
25702   else d0 = deinterpolate(d0, d1), r0 = reinterpolate(r0, r1);
25703   return function(x) { return r0(d0(x)); };
25704 }
25705
25706 function polymap(domain, range$$1, deinterpolate, reinterpolate) {
25707   var j = Math.min(domain.length, range$$1.length) - 1,
25708       d = new Array(j),
25709       r = new Array(j),
25710       i = -1;
25711
25712   // Reverse descending domains.
25713   if (domain[j] < domain[0]) {
25714     domain = domain.slice().reverse();
25715     range$$1 = range$$1.slice().reverse();
25716   }
25717
25718   while (++i < j) {
25719     d[i] = deinterpolate(domain[i], domain[i + 1]);
25720     r[i] = reinterpolate(range$$1[i], range$$1[i + 1]);
25721   }
25722
25723   return function(x) {
25724     var i = bisectRight(domain, x, 1, j) - 1;
25725     return r[i](d[i](x));
25726   };
25727 }
25728
25729 function copy(source, target) {
25730   return target
25731       .domain(source.domain())
25732       .range(source.range())
25733       .interpolate(source.interpolate())
25734       .clamp(source.clamp());
25735 }
25736
25737 // deinterpolate(a, b)(x) takes a domain value x in [a,b] and returns the corresponding parameter t in [0,1].
25738 // reinterpolate(a, b)(t) takes a parameter t in [0,1] and returns the corresponding domain value x in [a,b].
25739 function continuous(deinterpolate, reinterpolate) {
25740   var domain = unit,
25741       range$$1 = unit,
25742       interpolate$$1 = interpolate,
25743       clamp = false,
25744       piecewise,
25745       output,
25746       input;
25747
25748   function rescale() {
25749     piecewise = Math.min(domain.length, range$$1.length) > 2 ? polymap : bimap;
25750     output = input = null;
25751     return scale;
25752   }
25753
25754   function scale(x) {
25755     return (output || (output = piecewise(domain, range$$1, clamp ? deinterpolateClamp(deinterpolate) : deinterpolate, interpolate$$1)))(+x);
25756   }
25757
25758   scale.invert = function(y) {
25759     return (input || (input = piecewise(range$$1, domain, deinterpolateLinear, clamp ? reinterpolateClamp(reinterpolate) : reinterpolate)))(+y);
25760   };
25761
25762   scale.domain = function(_) {
25763     return arguments.length ? (domain = map$3.call(_, number$1), rescale()) : domain.slice();
25764   };
25765
25766   scale.range = function(_) {
25767     return arguments.length ? (range$$1 = slice$3.call(_), rescale()) : range$$1.slice();
25768   };
25769
25770   scale.rangeRound = function(_) {
25771     return range$$1 = slice$3.call(_), interpolate$$1 = interpolateRound, rescale();
25772   };
25773
25774   scale.clamp = function(_) {
25775     return arguments.length ? (clamp = !!_, rescale()) : clamp;
25776   };
25777
25778   scale.interpolate = function(_) {
25779     return arguments.length ? (interpolate$$1 = _, rescale()) : interpolate$$1;
25780   };
25781
25782   return rescale();
25783 }
25784
25785 var tickFormat = function(domain, count, specifier) {
25786   var start = domain[0],
25787       stop = domain[domain.length - 1],
25788       step = tickStep(start, stop, count == null ? 10 : count),
25789       precision;
25790   specifier = formatSpecifier(specifier == null ? ",f" : specifier);
25791   switch (specifier.type) {
25792     case "s": {
25793       var value = Math.max(Math.abs(start), Math.abs(stop));
25794       if (specifier.precision == null && !isNaN(precision = precisionPrefix(step, value))) specifier.precision = precision;
25795       return formatPrefix(specifier, value);
25796     }
25797     case "":
25798     case "e":
25799     case "g":
25800     case "p":
25801     case "r": {
25802       if (specifier.precision == null && !isNaN(precision = precisionRound(step, Math.max(Math.abs(start), Math.abs(stop))))) specifier.precision = precision - (specifier.type === "e");
25803       break;
25804     }
25805     case "f":
25806     case "%": {
25807       if (specifier.precision == null && !isNaN(precision = precisionFixed(step))) specifier.precision = precision - (specifier.type === "%") * 2;
25808       break;
25809     }
25810   }
25811   return format(specifier);
25812 };
25813
25814 function linearish(scale) {
25815   var domain = scale.domain;
25816
25817   scale.ticks = function(count) {
25818     var d = domain();
25819     return ticks(d[0], d[d.length - 1], count == null ? 10 : count);
25820   };
25821
25822   scale.tickFormat = function(count, specifier) {
25823     return tickFormat(domain(), count, specifier);
25824   };
25825
25826   scale.nice = function(count) {
25827     var d = domain(),
25828         i = d.length - 1,
25829         n = count == null ? 10 : count,
25830         start = d[0],
25831         stop = d[i],
25832         step = tickStep(start, stop, n);
25833
25834     if (step) {
25835       step = tickStep(Math.floor(start / step) * step, Math.ceil(stop / step) * step, n);
25836       d[0] = Math.floor(start / step) * step;
25837       d[i] = Math.ceil(stop / step) * step;
25838       domain(d);
25839     }
25840
25841     return scale;
25842   };
25843
25844   return scale;
25845 }
25846
25847 function linear$2() {
25848   var scale = continuous(deinterpolateLinear, interpolateNumber);
25849
25850   scale.copy = function() {
25851     return copy(scale, linear$2());
25852   };
25853
25854   return linearish(scale);
25855 }
25856
25857 function identity$4() {
25858   var domain = [0, 1];
25859
25860   function scale(x) {
25861     return +x;
25862   }
25863
25864   scale.invert = scale;
25865
25866   scale.domain = scale.range = function(_) {
25867     return arguments.length ? (domain = map$3.call(_, number$1), scale) : domain.slice();
25868   };
25869
25870   scale.copy = function() {
25871     return identity$4().domain(domain);
25872   };
25873
25874   return linearish(scale);
25875 }
25876
25877 var nice = function(domain, interval) {
25878   domain = domain.slice();
25879
25880   var i0 = 0,
25881       i1 = domain.length - 1,
25882       x0 = domain[i0],
25883       x1 = domain[i1],
25884       t;
25885
25886   if (x1 < x0) {
25887     t = i0, i0 = i1, i1 = t;
25888     t = x0, x0 = x1, x1 = t;
25889   }
25890
25891   domain[i0] = interval.floor(x0);
25892   domain[i1] = interval.ceil(x1);
25893   return domain;
25894 };
25895
25896 function deinterpolate(a, b) {
25897   return (b = Math.log(b / a))
25898       ? function(x) { return Math.log(x / a) / b; }
25899       : constant$4(b);
25900 }
25901
25902 function reinterpolate(a, b) {
25903   return a < 0
25904       ? function(t) { return -Math.pow(-b, t) * Math.pow(-a, 1 - t); }
25905       : function(t) { return Math.pow(b, t) * Math.pow(a, 1 - t); };
25906 }
25907
25908 function pow10(x) {
25909   return isFinite(x) ? +("1e" + x) : x < 0 ? 0 : x;
25910 }
25911
25912 function powp(base) {
25913   return base === 10 ? pow10
25914       : base === Math.E ? Math.exp
25915       : function(x) { return Math.pow(base, x); };
25916 }
25917
25918 function logp(base) {
25919   return base === Math.E ? Math.log
25920       : base === 10 && Math.log10
25921       || base === 2 && Math.log2
25922       || (base = Math.log(base), function(x) { return Math.log(x) / base; });
25923 }
25924
25925 function reflect(f) {
25926   return function(x) {
25927     return -f(-x);
25928   };
25929 }
25930
25931 function log() {
25932   var scale = continuous(deinterpolate, reinterpolate).domain([1, 10]),
25933       domain = scale.domain,
25934       base = 10,
25935       logs = logp(10),
25936       pows = powp(10);
25937
25938   function rescale() {
25939     logs = logp(base), pows = powp(base);
25940     if (domain()[0] < 0) logs = reflect(logs), pows = reflect(pows);
25941     return scale;
25942   }
25943
25944   scale.base = function(_) {
25945     return arguments.length ? (base = +_, rescale()) : base;
25946   };
25947
25948   scale.domain = function(_) {
25949     return arguments.length ? (domain(_), rescale()) : domain();
25950   };
25951
25952   scale.ticks = function(count) {
25953     var d = domain(),
25954         u = d[0],
25955         v = d[d.length - 1],
25956         r;
25957
25958     if (r = v < u) i = u, u = v, v = i;
25959
25960     var i = logs(u),
25961         j = logs(v),
25962         p,
25963         k,
25964         t,
25965         n = count == null ? 10 : +count,
25966         z = [];
25967
25968     if (!(base % 1) && j - i < n) {
25969       i = Math.round(i) - 1, j = Math.round(j) + 1;
25970       if (u > 0) for (; i < j; ++i) {
25971         for (k = 1, p = pows(i); k < base; ++k) {
25972           t = p * k;
25973           if (t < u) continue;
25974           if (t > v) break;
25975           z.push(t);
25976         }
25977       } else for (; i < j; ++i) {
25978         for (k = base - 1, p = pows(i); k >= 1; --k) {
25979           t = p * k;
25980           if (t < u) continue;
25981           if (t > v) break;
25982           z.push(t);
25983         }
25984       }
25985     } else {
25986       z = ticks(i, j, Math.min(j - i, n)).map(pows);
25987     }
25988
25989     return r ? z.reverse() : z;
25990   };
25991
25992   scale.tickFormat = function(count, specifier) {
25993     if (specifier == null) specifier = base === 10 ? ".0e" : ",";
25994     if (typeof specifier !== "function") specifier = format(specifier);
25995     if (count === Infinity) return specifier;
25996     if (count == null) count = 10;
25997     var k = Math.max(1, base * count / scale.ticks().length); // TODO fast estimate?
25998     return function(d) {
25999       var i = d / pows(Math.round(logs(d)));
26000       if (i * base < base - 0.5) i *= base;
26001       return i <= k ? specifier(d) : "";
26002     };
26003   };
26004
26005   scale.nice = function() {
26006     return domain(nice(domain(), {
26007       floor: function(x) { return pows(Math.floor(logs(x))); },
26008       ceil: function(x) { return pows(Math.ceil(logs(x))); }
26009     }));
26010   };
26011
26012   scale.copy = function() {
26013     return copy(scale, log().base(base));
26014   };
26015
26016   return scale;
26017 }
26018
26019 function raise(x, exponent) {
26020   return x < 0 ? -Math.pow(-x, exponent) : Math.pow(x, exponent);
26021 }
26022
26023 function pow() {
26024   var exponent = 1,
26025       scale = continuous(deinterpolate, reinterpolate),
26026       domain = scale.domain;
26027
26028   function deinterpolate(a, b) {
26029     return (b = raise(b, exponent) - (a = raise(a, exponent)))
26030         ? function(x) { return (raise(x, exponent) - a) / b; }
26031         : constant$4(b);
26032   }
26033
26034   function reinterpolate(a, b) {
26035     b = raise(b, exponent) - (a = raise(a, exponent));
26036     return function(t) { return raise(a + b * t, 1 / exponent); };
26037   }
26038
26039   scale.exponent = function(_) {
26040     return arguments.length ? (exponent = +_, domain(domain())) : exponent;
26041   };
26042
26043   scale.copy = function() {
26044     return copy(scale, pow().exponent(exponent));
26045   };
26046
26047   return linearish(scale);
26048 }
26049
26050 function sqrt() {
26051   return pow().exponent(0.5);
26052 }
26053
26054 function quantile$$1() {
26055   var domain = [],
26056       range$$1 = [],
26057       thresholds = [];
26058
26059   function rescale() {
26060     var i = 0, n = Math.max(1, range$$1.length);
26061     thresholds = new Array(n - 1);
26062     while (++i < n) thresholds[i - 1] = threshold(domain, i / n);
26063     return scale;
26064   }
26065
26066   function scale(x) {
26067     if (!isNaN(x = +x)) return range$$1[bisectRight(thresholds, x)];
26068   }
26069
26070   scale.invertExtent = function(y) {
26071     var i = range$$1.indexOf(y);
26072     return i < 0 ? [NaN, NaN] : [
26073       i > 0 ? thresholds[i - 1] : domain[0],
26074       i < thresholds.length ? thresholds[i] : domain[domain.length - 1]
26075     ];
26076   };
26077
26078   scale.domain = function(_) {
26079     if (!arguments.length) return domain.slice();
26080     domain = [];
26081     for (var i = 0, n = _.length, d; i < n; ++i) if (d = _[i], d != null && !isNaN(d = +d)) domain.push(d);
26082     domain.sort(ascending);
26083     return rescale();
26084   };
26085
26086   scale.range = function(_) {
26087     return arguments.length ? (range$$1 = slice$3.call(_), rescale()) : range$$1.slice();
26088   };
26089
26090   scale.quantiles = function() {
26091     return thresholds.slice();
26092   };
26093
26094   scale.copy = function() {
26095     return quantile$$1()
26096         .domain(domain)
26097         .range(range$$1);
26098   };
26099
26100   return scale;
26101 }
26102
26103 function quantize$1() {
26104   var x0 = 0,
26105       x1 = 1,
26106       n = 1,
26107       domain = [0.5],
26108       range$$1 = [0, 1];
26109
26110   function scale(x) {
26111     if (x <= x) return range$$1[bisectRight(domain, x, 0, n)];
26112   }
26113
26114   function rescale() {
26115     var i = -1;
26116     domain = new Array(n);
26117     while (++i < n) domain[i] = ((i + 1) * x1 - (i - n) * x0) / (n + 1);
26118     return scale;
26119   }
26120
26121   scale.domain = function(_) {
26122     return arguments.length ? (x0 = +_[0], x1 = +_[1], rescale()) : [x0, x1];
26123   };
26124
26125   scale.range = function(_) {
26126     return arguments.length ? (n = (range$$1 = slice$3.call(_)).length - 1, rescale()) : range$$1.slice();
26127   };
26128
26129   scale.invertExtent = function(y) {
26130     var i = range$$1.indexOf(y);
26131     return i < 0 ? [NaN, NaN]
26132         : i < 1 ? [x0, domain[0]]
26133         : i >= n ? [domain[n - 1], x1]
26134         : [domain[i - 1], domain[i]];
26135   };
26136
26137   scale.copy = function() {
26138     return quantize$1()
26139         .domain([x0, x1])
26140         .range(range$$1);
26141   };
26142
26143   return linearish(scale);
26144 }
26145
26146 function threshold$1() {
26147   var domain = [0.5],
26148       range$$1 = [0, 1],
26149       n = 1;
26150
26151   function scale(x) {
26152     if (x <= x) return range$$1[bisectRight(domain, x, 0, n)];
26153   }
26154
26155   scale.domain = function(_) {
26156     return arguments.length ? (domain = slice$3.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : domain.slice();
26157   };
26158
26159   scale.range = function(_) {
26160     return arguments.length ? (range$$1 = slice$3.call(_), n = Math.min(domain.length, range$$1.length - 1), scale) : range$$1.slice();
26161   };
26162
26163   scale.invertExtent = function(y) {
26164     var i = range$$1.indexOf(y);
26165     return [domain[i - 1], domain[i]];
26166   };
26167
26168   scale.copy = function() {
26169     return threshold$1()
26170         .domain(domain)
26171         .range(range$$1);
26172   };
26173
26174   return scale;
26175 }
26176
26177 var durationSecond$1 = 1000;
26178 var durationMinute$1 = durationSecond$1 * 60;
26179 var durationHour$1 = durationMinute$1 * 60;
26180 var durationDay$1 = durationHour$1 * 24;
26181 var durationWeek$1 = durationDay$1 * 7;
26182 var durationMonth = durationDay$1 * 30;
26183 var durationYear = durationDay$1 * 365;
26184
26185 function date$1(t) {
26186   return new Date(t);
26187 }
26188
26189 function number$2(t) {
26190   return t instanceof Date ? +t : +new Date(+t);
26191 }
26192
26193 function calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format) {
26194   var scale = continuous(deinterpolateLinear, interpolateNumber),
26195       invert = scale.invert,
26196       domain = scale.domain;
26197
26198   var formatMillisecond = format(".%L"),
26199       formatSecond = format(":%S"),
26200       formatMinute = format("%I:%M"),
26201       formatHour = format("%I %p"),
26202       formatDay = format("%a %d"),
26203       formatWeek = format("%b %d"),
26204       formatMonth = format("%B"),
26205       formatYear = format("%Y");
26206
26207   var tickIntervals = [
26208     [second$$1,  1,      durationSecond$1],
26209     [second$$1,  5,  5 * durationSecond$1],
26210     [second$$1, 15, 15 * durationSecond$1],
26211     [second$$1, 30, 30 * durationSecond$1],
26212     [minute$$1,  1,      durationMinute$1],
26213     [minute$$1,  5,  5 * durationMinute$1],
26214     [minute$$1, 15, 15 * durationMinute$1],
26215     [minute$$1, 30, 30 * durationMinute$1],
26216     [  hour$$1,  1,      durationHour$1  ],
26217     [  hour$$1,  3,  3 * durationHour$1  ],
26218     [  hour$$1,  6,  6 * durationHour$1  ],
26219     [  hour$$1, 12, 12 * durationHour$1  ],
26220     [   day$$1,  1,      durationDay$1   ],
26221     [   day$$1,  2,  2 * durationDay$1   ],
26222     [  week,  1,      durationWeek$1  ],
26223     [ month$$1,  1,      durationMonth ],
26224     [ month$$1,  3,  3 * durationMonth ],
26225     [  year$$1,  1,      durationYear  ]
26226   ];
26227
26228   function tickFormat(date) {
26229     return (second$$1(date) < date ? formatMillisecond
26230         : minute$$1(date) < date ? formatSecond
26231         : hour$$1(date) < date ? formatMinute
26232         : day$$1(date) < date ? formatHour
26233         : month$$1(date) < date ? (week(date) < date ? formatDay : formatWeek)
26234         : year$$1(date) < date ? formatMonth
26235         : formatYear)(date);
26236   }
26237
26238   function tickInterval(interval, start, stop, step) {
26239     if (interval == null) interval = 10;
26240
26241     // If a desired tick count is specified, pick a reasonable tick interval
26242     // based on the extent of the domain and a rough estimate of tick size.
26243     // Otherwise, assume interval is already a time interval and use it.
26244     if (typeof interval === "number") {
26245       var target = Math.abs(stop - start) / interval,
26246           i = bisector(function(i) { return i[2]; }).right(tickIntervals, target);
26247       if (i === tickIntervals.length) {
26248         step = tickStep(start / durationYear, stop / durationYear, interval);
26249         interval = year$$1;
26250       } else if (i) {
26251         i = tickIntervals[target / tickIntervals[i - 1][2] < tickIntervals[i][2] / target ? i - 1 : i];
26252         step = i[1];
26253         interval = i[0];
26254       } else {
26255         step = tickStep(start, stop, interval);
26256         interval = millisecond$$1;
26257       }
26258     }
26259
26260     return step == null ? interval : interval.every(step);
26261   }
26262
26263   scale.invert = function(y) {
26264     return new Date(invert(y));
26265   };
26266
26267   scale.domain = function(_) {
26268     return arguments.length ? domain(map$3.call(_, number$2)) : domain().map(date$1);
26269   };
26270
26271   scale.ticks = function(interval, step) {
26272     var d = domain(),
26273         t0 = d[0],
26274         t1 = d[d.length - 1],
26275         r = t1 < t0,
26276         t;
26277     if (r) t = t0, t0 = t1, t1 = t;
26278     t = tickInterval(interval, t0, t1, step);
26279     t = t ? t.range(t0, t1 + 1) : []; // inclusive stop
26280     return r ? t.reverse() : t;
26281   };
26282
26283   scale.tickFormat = function(count, specifier) {
26284     return specifier == null ? tickFormat : format(specifier);
26285   };
26286
26287   scale.nice = function(interval, step) {
26288     var d = domain();
26289     return (interval = tickInterval(interval, d[0], d[d.length - 1], step))
26290         ? domain(nice(d, interval))
26291         : scale;
26292   };
26293
26294   scale.copy = function() {
26295     return copy(scale, calendar(year$$1, month$$1, week, day$$1, hour$$1, minute$$1, second$$1, millisecond$$1, format));
26296   };
26297
26298   return scale;
26299 }
26300
26301 var time = function() {
26302   return calendar(year, month, sunday, day, hour, minute, second, millisecond, timeFormat).domain([new Date(2000, 0, 1), new Date(2000, 0, 2)]);
26303 };
26304
26305 var utcTime = function() {
26306   return calendar(utcYear, utcMonth, utcSunday, utcDay, utcHour, utcMinute, second, millisecond, utcFormat).domain([Date.UTC(2000, 0, 1), Date.UTC(2000, 0, 2)]);
26307 };
26308
26309 var colors = function(s) {
26310   return s.match(/.{6}/g).map(function(x) {
26311     return "#" + x;
26312   });
26313 };
26314
26315 var category10 = colors("1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf");
26316
26317 var category20b = colors("393b795254a36b6ecf9c9ede6379398ca252b5cf6bcedb9c8c6d31bd9e39e7ba52e7cb94843c39ad494ad6616be7969c7b4173a55194ce6dbdde9ed6");
26318
26319 var category20c = colors("3182bd6baed69ecae1c6dbefe6550dfd8d3cfdae6bfdd0a231a35474c476a1d99bc7e9c0756bb19e9ac8bcbddcdadaeb636363969696bdbdbdd9d9d9");
26320
26321 var category20 = colors("1f77b4aec7e8ff7f0effbb782ca02c98df8ad62728ff98969467bdc5b0d58c564bc49c94e377c2f7b6d27f7f7fc7c7c7bcbd22dbdb8d17becf9edae5");
26322
26323 var cubehelix$3 = cubehelixLong(cubehelix(300, 0.5, 0.0), cubehelix(-240, 0.5, 1.0));
26324
26325 var warm = cubehelixLong(cubehelix(-100, 0.75, 0.35), cubehelix(80, 1.50, 0.8));
26326
26327 var cool = cubehelixLong(cubehelix(260, 0.75, 0.35), cubehelix(80, 1.50, 0.8));
26328
26329 var rainbow = cubehelix();
26330
26331 var rainbow$1 = function(t) {
26332   if (t < 0 || t > 1) t -= Math.floor(t);
26333   var ts = Math.abs(t - 0.5);
26334   rainbow.h = 360 * t - 100;
26335   rainbow.s = 1.5 - 1.5 * ts;
26336   rainbow.l = 0.8 - 0.9 * ts;
26337   return rainbow + "";
26338 };
26339
26340 function ramp(range) {
26341   var n = range.length;
26342   return function(t) {
26343     return range[Math.max(0, Math.min(n - 1, Math.floor(t * n)))];
26344   };
26345 }
26346
26347 var viridis = ramp(colors("44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725"));
26348
26349 var magma = ramp(colors("00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf"));
26350
26351 var inferno = ramp(colors("00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4"));
26352
26353 var plasma = ramp(colors("0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921"));
26354
26355 function sequential(interpolator) {
26356   var x0 = 0,
26357       x1 = 1,
26358       clamp = false;
26359
26360   function scale(x) {
26361     var t = (x - x0) / (x1 - x0);
26362     return interpolator(clamp ? Math.max(0, Math.min(1, t)) : t);
26363   }
26364
26365   scale.domain = function(_) {
26366     return arguments.length ? (x0 = +_[0], x1 = +_[1], scale) : [x0, x1];
26367   };
26368
26369   scale.clamp = function(_) {
26370     return arguments.length ? (clamp = !!_, scale) : clamp;
26371   };
26372
26373   scale.interpolator = function(_) {
26374     return arguments.length ? (interpolator = _, scale) : interpolator;
26375   };
26376
26377   scale.copy = function() {
26378     return sequential(interpolator).domain([x0, x1]).clamp(clamp);
26379   };
26380
26381   return linearish(scale);
26382 }
26383
26384 var xhtml = "http://www.w3.org/1999/xhtml";
26385
26386 var namespaces = {
26387   svg: "http://www.w3.org/2000/svg",
26388   xhtml: xhtml,
26389   xlink: "http://www.w3.org/1999/xlink",
26390   xml: "http://www.w3.org/XML/1998/namespace",
26391   xmlns: "http://www.w3.org/2000/xmlns/"
26392 };
26393
26394 var namespace = function(name) {
26395   var prefix = name += "", i = prefix.indexOf(":");
26396   if (i >= 0 && (prefix = name.slice(0, i)) !== "xmlns") name = name.slice(i + 1);
26397   return namespaces.hasOwnProperty(prefix) ? {space: namespaces[prefix], local: name} : name;
26398 };
26399
26400 function creatorInherit(name) {
26401   return function() {
26402     var document = this.ownerDocument,
26403         uri = this.namespaceURI;
26404     return uri === xhtml && document.documentElement.namespaceURI === xhtml
26405         ? document.createElement(name)
26406         : document.createElementNS(uri, name);
26407   };
26408 }
26409
26410 function creatorFixed(fullname) {
26411   return function() {
26412     return this.ownerDocument.createElementNS(fullname.space, fullname.local);
26413   };
26414 }
26415
26416 var creator = function(name) {
26417   var fullname = namespace(name);
26418   return (fullname.local
26419       ? creatorFixed
26420       : creatorInherit)(fullname);
26421 };
26422
26423 var nextId = 0;
26424
26425 function local() {
26426   return new Local;
26427 }
26428
26429 function Local() {
26430   this._ = "@" + (++nextId).toString(36);
26431 }
26432
26433 Local.prototype = local.prototype = {
26434   constructor: Local,
26435   get: function(node) {
26436     var id = this._;
26437     while (!(id in node)) if (!(node = node.parentNode)) return;
26438     return node[id];
26439   },
26440   set: function(node, value) {
26441     return node[this._] = value;
26442   },
26443   remove: function(node) {
26444     return this._ in node && delete node[this._];
26445   },
26446   toString: function() {
26447     return this._;
26448   }
26449 };
26450
26451 var matcher = function(selector) {
26452   return function() {
26453     return this.matches(selector);
26454   };
26455 };
26456
26457 if (typeof document !== "undefined") {
26458   var element = document.documentElement;
26459   if (!element.matches) {
26460     var vendorMatches = element.webkitMatchesSelector
26461         || element.msMatchesSelector
26462         || element.mozMatchesSelector
26463         || element.oMatchesSelector;
26464     matcher = function(selector) {
26465       return function() {
26466         return vendorMatches.call(this, selector);
26467       };
26468     };
26469   }
26470 }
26471
26472 var matcher$1 = matcher;
26473
26474 var filterEvents = {};
26475
26476 var event = null;
26477
26478 if (typeof document !== "undefined") {
26479   var element$1 = document.documentElement;
26480   if (!("onmouseenter" in element$1)) {
26481     filterEvents = {mouseenter: "mouseover", mouseleave: "mouseout"};
26482   }
26483 }
26484
26485 function filterContextListener(listener, index, group) {
26486   listener = contextListener(listener, index, group);
26487   return function(event) {
26488     var related = event.relatedTarget;
26489     if (!related || (related !== this && !(related.compareDocumentPosition(this) & 8))) {
26490       listener.call(this, event);
26491     }
26492   };
26493 }
26494
26495 function contextListener(listener, index, group) {
26496   return function(event1) {
26497     var event0 = event; // Events can be reentrant (e.g., focus).
26498     event = event1;
26499     try {
26500       listener.call(this, this.__data__, index, group);
26501     } finally {
26502       event = event0;
26503     }
26504   };
26505 }
26506
26507 function parseTypenames$1(typenames) {
26508   return typenames.trim().split(/^|\s+/).map(function(t) {
26509     var name = "", i = t.indexOf(".");
26510     if (i >= 0) name = t.slice(i + 1), t = t.slice(0, i);
26511     return {type: t, name: name};
26512   });
26513 }
26514
26515 function onRemove(typename) {
26516   return function() {
26517     var on = this.__on;
26518     if (!on) return;
26519     for (var j = 0, i = -1, m = on.length, o; j < m; ++j) {
26520       if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) {
26521         this.removeEventListener(o.type, o.listener, o.capture);
26522       } else {
26523         on[++i] = o;
26524       }
26525     }
26526     if (++i) on.length = i;
26527     else delete this.__on;
26528   };
26529 }
26530
26531 function onAdd(typename, value, capture) {
26532   var wrap = filterEvents.hasOwnProperty(typename.type) ? filterContextListener : contextListener;
26533   return function(d, i, group) {
26534     var on = this.__on, o, listener = wrap(value, i, group);
26535     if (on) for (var j = 0, m = on.length; j < m; ++j) {
26536       if ((o = on[j]).type === typename.type && o.name === typename.name) {
26537         this.removeEventListener(o.type, o.listener, o.capture);
26538         this.addEventListener(o.type, o.listener = listener, o.capture = capture);
26539         o.value = value;
26540         return;
26541       }
26542     }
26543     this.addEventListener(typename.type, listener, capture);
26544     o = {type: typename.type, name: typename.name, value: value, listener: listener, capture: capture};
26545     if (!on) this.__on = [o];
26546     else on.push(o);
26547   };
26548 }
26549
26550 var selection_on = function(typename, value, capture) {
26551   var typenames = parseTypenames$1(typename + ""), i, n = typenames.length, t;
26552
26553   if (arguments.length < 2) {
26554     var on = this.node().__on;
26555     if (on) for (var j = 0, m = on.length, o; j < m; ++j) {
26556       for (i = 0, o = on[j]; i < n; ++i) {
26557         if ((t = typenames[i]).type === o.type && t.name === o.name) {
26558           return o.value;
26559         }
26560       }
26561     }
26562     return;
26563   }
26564
26565   on = value ? onAdd : onRemove;
26566   if (capture == null) capture = false;
26567   for (i = 0; i < n; ++i) this.each(on(typenames[i], value, capture));
26568   return this;
26569 };
26570
26571 function customEvent(event1, listener, that, args) {
26572   var event0 = event;
26573   event1.sourceEvent = event;
26574   event = event1;
26575   try {
26576     return listener.apply(that, args);
26577   } finally {
26578     event = event0;
26579   }
26580 }
26581
26582 var sourceEvent = function() {
26583   var current = event, source;
26584   while (source = current.sourceEvent) current = source;
26585   return current;
26586 };
26587
26588 var point$5 = function(node, event) {
26589   var svg = node.ownerSVGElement || node;
26590
26591   if (svg.createSVGPoint) {
26592     var point = svg.createSVGPoint();
26593     point.x = event.clientX, point.y = event.clientY;
26594     point = point.matrixTransform(node.getScreenCTM().inverse());
26595     return [point.x, point.y];
26596   }
26597
26598   var rect = node.getBoundingClientRect();
26599   return [event.clientX - rect.left - node.clientLeft, event.clientY - rect.top - node.clientTop];
26600 };
26601
26602 var mouse = function(node) {
26603   var event = sourceEvent();
26604   if (event.changedTouches) event = event.changedTouches[0];
26605   return point$5(node, event);
26606 };
26607
26608 function none$2() {}
26609
26610 var selector = function(selector) {
26611   return selector == null ? none$2 : function() {
26612     return this.querySelector(selector);
26613   };
26614 };
26615
26616 var selection_select = function(select) {
26617   if (typeof select !== "function") select = selector(select);
26618
26619   for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
26620     for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
26621       if ((node = group[i]) && (subnode = select.call(node, node.__data__, i, group))) {
26622         if ("__data__" in node) subnode.__data__ = node.__data__;
26623         subgroup[i] = subnode;
26624       }
26625     }
26626   }
26627
26628   return new Selection(subgroups, this._parents);
26629 };
26630
26631 function empty() {
26632   return [];
26633 }
26634
26635 var selectorAll = function(selector) {
26636   return selector == null ? empty : function() {
26637     return this.querySelectorAll(selector);
26638   };
26639 };
26640
26641 var selection_selectAll = function(select) {
26642   if (typeof select !== "function") select = selectorAll(select);
26643
26644   for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
26645     for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
26646       if (node = group[i]) {
26647         subgroups.push(select.call(node, node.__data__, i, group));
26648         parents.push(node);
26649       }
26650     }
26651   }
26652
26653   return new Selection(subgroups, parents);
26654 };
26655
26656 var selection_filter = function(match) {
26657   if (typeof match !== "function") match = matcher$1(match);
26658
26659   for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
26660     for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
26661       if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
26662         subgroup.push(node);
26663       }
26664     }
26665   }
26666
26667   return new Selection(subgroups, this._parents);
26668 };
26669
26670 var sparse = function(update) {
26671   return new Array(update.length);
26672 };
26673
26674 var selection_enter = function() {
26675   return new Selection(this._enter || this._groups.map(sparse), this._parents);
26676 };
26677
26678 function EnterNode(parent, datum) {
26679   this.ownerDocument = parent.ownerDocument;
26680   this.namespaceURI = parent.namespaceURI;
26681   this._next = null;
26682   this._parent = parent;
26683   this.__data__ = datum;
26684 }
26685
26686 EnterNode.prototype = {
26687   constructor: EnterNode,
26688   appendChild: function(child) { return this._parent.insertBefore(child, this._next); },
26689   insertBefore: function(child, next) { return this._parent.insertBefore(child, next); },
26690   querySelector: function(selector) { return this._parent.querySelector(selector); },
26691   querySelectorAll: function(selector) { return this._parent.querySelectorAll(selector); }
26692 };
26693
26694 var constant$5 = function(x) {
26695   return function() {
26696     return x;
26697   };
26698 };
26699
26700 var keyPrefix = "$"; // Protect against keys like “__proto__”.
26701
26702 function bindIndex(parent, group, enter, update, exit, data) {
26703   var i = 0,
26704       node,
26705       groupLength = group.length,
26706       dataLength = data.length;
26707
26708   // Put any non-null nodes that fit into update.
26709   // Put any null nodes into enter.
26710   // Put any remaining data into enter.
26711   for (; i < dataLength; ++i) {
26712     if (node = group[i]) {
26713       node.__data__ = data[i];
26714       update[i] = node;
26715     } else {
26716       enter[i] = new EnterNode(parent, data[i]);
26717     }
26718   }
26719
26720   // Put any non-null nodes that don’t fit into exit.
26721   for (; i < groupLength; ++i) {
26722     if (node = group[i]) {
26723       exit[i] = node;
26724     }
26725   }
26726 }
26727
26728 function bindKey(parent, group, enter, update, exit, data, key) {
26729   var i,
26730       node,
26731       nodeByKeyValue = {},
26732       groupLength = group.length,
26733       dataLength = data.length,
26734       keyValues = new Array(groupLength),
26735       keyValue;
26736
26737   // Compute the key for each node.
26738   // If multiple nodes have the same key, the duplicates are added to exit.
26739   for (i = 0; i < groupLength; ++i) {
26740     if (node = group[i]) {
26741       keyValues[i] = keyValue = keyPrefix + key.call(node, node.__data__, i, group);
26742       if (keyValue in nodeByKeyValue) {
26743         exit[i] = node;
26744       } else {
26745         nodeByKeyValue[keyValue] = node;
26746       }
26747     }
26748   }
26749
26750   // Compute the key for each datum.
26751   // If there a node associated with this key, join and add it to update.
26752   // If there is not (or the key is a duplicate), add it to enter.
26753   for (i = 0; i < dataLength; ++i) {
26754     keyValue = keyPrefix + key.call(parent, data[i], i, data);
26755     if (node = nodeByKeyValue[keyValue]) {
26756       update[i] = node;
26757       node.__data__ = data[i];
26758       nodeByKeyValue[keyValue] = null;
26759     } else {
26760       enter[i] = new EnterNode(parent, data[i]);
26761     }
26762   }
26763
26764   // Add any remaining nodes that were not bound to data to exit.
26765   for (i = 0; i < groupLength; ++i) {
26766     if ((node = group[i]) && (nodeByKeyValue[keyValues[i]] === node)) {
26767       exit[i] = node;
26768     }
26769   }
26770 }
26771
26772 var selection_data = function(value, key) {
26773   if (!value) {
26774     data = new Array(this.size()), j = -1;
26775     this.each(function(d) { data[++j] = d; });
26776     return data;
26777   }
26778
26779   var bind = key ? bindKey : bindIndex,
26780       parents = this._parents,
26781       groups = this._groups;
26782
26783   if (typeof value !== "function") value = constant$5(value);
26784
26785   for (var m = groups.length, update = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) {
26786     var parent = parents[j],
26787         group = groups[j],
26788         groupLength = group.length,
26789         data = value.call(parent, parent && parent.__data__, j, parents),
26790         dataLength = data.length,
26791         enterGroup = enter[j] = new Array(dataLength),
26792         updateGroup = update[j] = new Array(dataLength),
26793         exitGroup = exit[j] = new Array(groupLength);
26794
26795     bind(parent, group, enterGroup, updateGroup, exitGroup, data, key);
26796
26797     // Now connect the enter nodes to their following update node, such that
26798     // appendChild can insert the materialized enter node before this node,
26799     // rather than at the end of the parent node.
26800     for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) {
26801       if (previous = enterGroup[i0]) {
26802         if (i0 >= i1) i1 = i0 + 1;
26803         while (!(next = updateGroup[i1]) && ++i1 < dataLength);
26804         previous._next = next || null;
26805       }
26806     }
26807   }
26808
26809   update = new Selection(update, parents);
26810   update._enter = enter;
26811   update._exit = exit;
26812   return update;
26813 };
26814
26815 var selection_exit = function() {
26816   return new Selection(this._exit || this._groups.map(sparse), this._parents);
26817 };
26818
26819 var selection_merge = function(selection) {
26820
26821   for (var groups0 = this._groups, groups1 = selection._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) {
26822     for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
26823       if (node = group0[i] || group1[i]) {
26824         merge[i] = node;
26825       }
26826     }
26827   }
26828
26829   for (; j < m0; ++j) {
26830     merges[j] = groups0[j];
26831   }
26832
26833   return new Selection(merges, this._parents);
26834 };
26835
26836 var selection_order = function() {
26837
26838   for (var groups = this._groups, j = -1, m = groups.length; ++j < m;) {
26839     for (var group = groups[j], i = group.length - 1, next = group[i], node; --i >= 0;) {
26840       if (node = group[i]) {
26841         if (next && next !== node.nextSibling) next.parentNode.insertBefore(node, next);
26842         next = node;
26843       }
26844     }
26845   }
26846
26847   return this;
26848 };
26849
26850 var selection_sort = function(compare) {
26851   if (!compare) compare = ascending$2;
26852
26853   function compareNode(a, b) {
26854     return a && b ? compare(a.__data__, b.__data__) : !a - !b;
26855   }
26856
26857   for (var groups = this._groups, m = groups.length, sortgroups = new Array(m), j = 0; j < m; ++j) {
26858     for (var group = groups[j], n = group.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) {
26859       if (node = group[i]) {
26860         sortgroup[i] = node;
26861       }
26862     }
26863     sortgroup.sort(compareNode);
26864   }
26865
26866   return new Selection(sortgroups, this._parents).order();
26867 };
26868
26869 function ascending$2(a, b) {
26870   return a < b ? -1 : a > b ? 1 : a >= b ? 0 : NaN;
26871 }
26872
26873 var selection_call = function() {
26874   var callback = arguments[0];
26875   arguments[0] = this;
26876   callback.apply(null, arguments);
26877   return this;
26878 };
26879
26880 var selection_nodes = function() {
26881   var nodes = new Array(this.size()), i = -1;
26882   this.each(function() { nodes[++i] = this; });
26883   return nodes;
26884 };
26885
26886 var selection_node = function() {
26887
26888   for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
26889     for (var group = groups[j], i = 0, n = group.length; i < n; ++i) {
26890       var node = group[i];
26891       if (node) return node;
26892     }
26893   }
26894
26895   return null;
26896 };
26897
26898 var selection_size = function() {
26899   var size = 0;
26900   this.each(function() { ++size; });
26901   return size;
26902 };
26903
26904 var selection_empty = function() {
26905   return !this.node();
26906 };
26907
26908 var selection_each = function(callback) {
26909
26910   for (var groups = this._groups, j = 0, m = groups.length; j < m; ++j) {
26911     for (var group = groups[j], i = 0, n = group.length, node; i < n; ++i) {
26912       if (node = group[i]) callback.call(node, node.__data__, i, group);
26913     }
26914   }
26915
26916   return this;
26917 };
26918
26919 function attrRemove(name) {
26920   return function() {
26921     this.removeAttribute(name);
26922   };
26923 }
26924
26925 function attrRemoveNS(fullname) {
26926   return function() {
26927     this.removeAttributeNS(fullname.space, fullname.local);
26928   };
26929 }
26930
26931 function attrConstant(name, value) {
26932   return function() {
26933     this.setAttribute(name, value);
26934   };
26935 }
26936
26937 function attrConstantNS(fullname, value) {
26938   return function() {
26939     this.setAttributeNS(fullname.space, fullname.local, value);
26940   };
26941 }
26942
26943 function attrFunction(name, value) {
26944   return function() {
26945     var v = value.apply(this, arguments);
26946     if (v == null) this.removeAttribute(name);
26947     else this.setAttribute(name, v);
26948   };
26949 }
26950
26951 function attrFunctionNS(fullname, value) {
26952   return function() {
26953     var v = value.apply(this, arguments);
26954     if (v == null) this.removeAttributeNS(fullname.space, fullname.local);
26955     else this.setAttributeNS(fullname.space, fullname.local, v);
26956   };
26957 }
26958
26959 var selection_attr = function(name, value) {
26960   var fullname = namespace(name);
26961
26962   if (arguments.length < 2) {
26963     var node = this.node();
26964     return fullname.local
26965         ? node.getAttributeNS(fullname.space, fullname.local)
26966         : node.getAttribute(fullname);
26967   }
26968
26969   return this.each((value == null
26970       ? (fullname.local ? attrRemoveNS : attrRemove) : (typeof value === "function"
26971       ? (fullname.local ? attrFunctionNS : attrFunction)
26972       : (fullname.local ? attrConstantNS : attrConstant)))(fullname, value));
26973 };
26974
26975 var window$1 = function(node) {
26976   return (node.ownerDocument && node.ownerDocument.defaultView) // node is a Node
26977       || (node.document && node) // node is a Window
26978       || node.defaultView; // node is a Document
26979 };
26980
26981 function styleRemove(name) {
26982   return function() {
26983     this.style.removeProperty(name);
26984   };
26985 }
26986
26987 function styleConstant(name, value, priority) {
26988   return function() {
26989     this.style.setProperty(name, value, priority);
26990   };
26991 }
26992
26993 function styleFunction(name, value, priority) {
26994   return function() {
26995     var v = value.apply(this, arguments);
26996     if (v == null) this.style.removeProperty(name);
26997     else this.style.setProperty(name, v, priority);
26998   };
26999 }
27000
27001 var selection_style = function(name, value, priority) {
27002   var node;
27003   return arguments.length > 1
27004       ? this.each((value == null
27005             ? styleRemove : typeof value === "function"
27006             ? styleFunction
27007             : styleConstant)(name, value, priority == null ? "" : priority))
27008       : window$1(node = this.node())
27009           .getComputedStyle(node, null)
27010           .getPropertyValue(name);
27011 };
27012
27013 function propertyRemove(name) {
27014   return function() {
27015     delete this[name];
27016   };
27017 }
27018
27019 function propertyConstant(name, value) {
27020   return function() {
27021     this[name] = value;
27022   };
27023 }
27024
27025 function propertyFunction(name, value) {
27026   return function() {
27027     var v = value.apply(this, arguments);
27028     if (v == null) delete this[name];
27029     else this[name] = v;
27030   };
27031 }
27032
27033 var selection_property = function(name, value) {
27034   return arguments.length > 1
27035       ? this.each((value == null
27036           ? propertyRemove : typeof value === "function"
27037           ? propertyFunction
27038           : propertyConstant)(name, value))
27039       : this.node()[name];
27040 };
27041
27042 function classArray(string) {
27043   return string.trim().split(/^|\s+/);
27044 }
27045
27046 function classList(node) {
27047   return node.classList || new ClassList(node);
27048 }
27049
27050 function ClassList(node) {
27051   this._node = node;
27052   this._names = classArray(node.getAttribute("class") || "");
27053 }
27054
27055 ClassList.prototype = {
27056   add: function(name) {
27057     var i = this._names.indexOf(name);
27058     if (i < 0) {
27059       this._names.push(name);
27060       this._node.setAttribute("class", this._names.join(" "));
27061     }
27062   },
27063   remove: function(name) {
27064     var i = this._names.indexOf(name);
27065     if (i >= 0) {
27066       this._names.splice(i, 1);
27067       this._node.setAttribute("class", this._names.join(" "));
27068     }
27069   },
27070   contains: function(name) {
27071     return this._names.indexOf(name) >= 0;
27072   }
27073 };
27074
27075 function classedAdd(node, names) {
27076   var list = classList(node), i = -1, n = names.length;
27077   while (++i < n) list.add(names[i]);
27078 }
27079
27080 function classedRemove(node, names) {
27081   var list = classList(node), i = -1, n = names.length;
27082   while (++i < n) list.remove(names[i]);
27083 }
27084
27085 function classedTrue(names) {
27086   return function() {
27087     classedAdd(this, names);
27088   };
27089 }
27090
27091 function classedFalse(names) {
27092   return function() {
27093     classedRemove(this, names);
27094   };
27095 }
27096
27097 function classedFunction(names, value) {
27098   return function() {
27099     (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names);
27100   };
27101 }
27102
27103 var selection_classed = function(name, value) {
27104   var names = classArray(name + "");
27105
27106   if (arguments.length < 2) {
27107     var list = classList(this.node()), i = -1, n = names.length;
27108     while (++i < n) if (!list.contains(names[i])) return false;
27109     return true;
27110   }
27111
27112   return this.each((typeof value === "function"
27113       ? classedFunction : value
27114       ? classedTrue
27115       : classedFalse)(names, value));
27116 };
27117
27118 function textRemove() {
27119   this.textContent = "";
27120 }
27121
27122 function textConstant(value) {
27123   return function() {
27124     this.textContent = value;
27125   };
27126 }
27127
27128 function textFunction(value) {
27129   return function() {
27130     var v = value.apply(this, arguments);
27131     this.textContent = v == null ? "" : v;
27132   };
27133 }
27134
27135 var selection_text = function(value) {
27136   return arguments.length
27137       ? this.each(value == null
27138           ? textRemove : (typeof value === "function"
27139           ? textFunction
27140           : textConstant)(value))
27141       : this.node().textContent;
27142 };
27143
27144 function htmlRemove() {
27145   this.innerHTML = "";
27146 }
27147
27148 function htmlConstant(value) {
27149   return function() {
27150     this.innerHTML = value;
27151   };
27152 }
27153
27154 function htmlFunction(value) {
27155   return function() {
27156     var v = value.apply(this, arguments);
27157     this.innerHTML = v == null ? "" : v;
27158   };
27159 }
27160
27161 var selection_html = function(value) {
27162   return arguments.length
27163       ? this.each(value == null
27164           ? htmlRemove : (typeof value === "function"
27165           ? htmlFunction
27166           : htmlConstant)(value))
27167       : this.node().innerHTML;
27168 };
27169
27170 function raise$1() {
27171   if (this.nextSibling) this.parentNode.appendChild(this);
27172 }
27173
27174 var selection_raise = function() {
27175   return this.each(raise$1);
27176 };
27177
27178 function lower() {
27179   if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild);
27180 }
27181
27182 var selection_lower = function() {
27183   return this.each(lower);
27184 };
27185
27186 var selection_append = function(name) {
27187   var create = typeof name === "function" ? name : creator(name);
27188   return this.select(function() {
27189     return this.appendChild(create.apply(this, arguments));
27190   });
27191 };
27192
27193 function constantNull() {
27194   return null;
27195 }
27196
27197 var selection_insert = function(name, before) {
27198   var create = typeof name === "function" ? name : creator(name),
27199       select = before == null ? constantNull : typeof before === "function" ? before : selector(before);
27200   return this.select(function() {
27201     return this.insertBefore(create.apply(this, arguments), select.apply(this, arguments) || null);
27202   });
27203 };
27204
27205 function remove() {
27206   var parent = this.parentNode;
27207   if (parent) parent.removeChild(this);
27208 }
27209
27210 var selection_remove = function() {
27211   return this.each(remove);
27212 };
27213
27214 var selection_datum = function(value) {
27215   return arguments.length
27216       ? this.property("__data__", value)
27217       : this.node().__data__;
27218 };
27219
27220 function dispatchEvent(node, type, params) {
27221   var window = window$1(node),
27222       event = window.CustomEvent;
27223
27224   if (event) {
27225     event = new event(type, params);
27226   } else {
27227     event = window.document.createEvent("Event");
27228     if (params) event.initEvent(type, params.bubbles, params.cancelable), event.detail = params.detail;
27229     else event.initEvent(type, false, false);
27230   }
27231
27232   node.dispatchEvent(event);
27233 }
27234
27235 function dispatchConstant(type, params) {
27236   return function() {
27237     return dispatchEvent(this, type, params);
27238   };
27239 }
27240
27241 function dispatchFunction(type, params) {
27242   return function() {
27243     return dispatchEvent(this, type, params.apply(this, arguments));
27244   };
27245 }
27246
27247 var selection_dispatch = function(type, params) {
27248   return this.each((typeof params === "function"
27249       ? dispatchFunction
27250       : dispatchConstant)(type, params));
27251 };
27252
27253 var root = [null];
27254
27255 function Selection(groups, parents) {
27256   this._groups = groups;
27257   this._parents = parents;
27258 }
27259
27260 function selection() {
27261   return new Selection([[document.documentElement]], root);
27262 }
27263
27264 Selection.prototype = selection.prototype = {
27265   constructor: Selection,
27266   select: selection_select,
27267   selectAll: selection_selectAll,
27268   filter: selection_filter,
27269   data: selection_data,
27270   enter: selection_enter,
27271   exit: selection_exit,
27272   merge: selection_merge,
27273   order: selection_order,
27274   sort: selection_sort,
27275   call: selection_call,
27276   nodes: selection_nodes,
27277   node: selection_node,
27278   size: selection_size,
27279   empty: selection_empty,
27280   each: selection_each,
27281   attr: selection_attr,
27282   style: selection_style,
27283   property: selection_property,
27284   classed: selection_classed,
27285   text: selection_text,
27286   html: selection_html,
27287   raise: selection_raise,
27288   lower: selection_lower,
27289   append: selection_append,
27290   insert: selection_insert,
27291   remove: selection_remove,
27292   datum: selection_datum,
27293   on: selection_on,
27294   dispatch: selection_dispatch
27295 };
27296
27297 var select = function(selector) {
27298   return typeof selector === "string"
27299       ? new Selection([[document.querySelector(selector)]], [document.documentElement])
27300       : new Selection([[selector]], root);
27301 };
27302
27303 var selectAll = function(selector) {
27304   return typeof selector === "string"
27305       ? new Selection([document.querySelectorAll(selector)], [document.documentElement])
27306       : new Selection([selector == null ? [] : selector], root);
27307 };
27308
27309 var touch = function(node, touches, identifier) {
27310   if (arguments.length < 3) identifier = touches, touches = sourceEvent().changedTouches;
27311
27312   for (var i = 0, n = touches ? touches.length : 0, touch; i < n; ++i) {
27313     if ((touch = touches[i]).identifier === identifier) {
27314       return point$5(node, touch);
27315     }
27316   }
27317
27318   return null;
27319 };
27320
27321 var touches = function(node, touches) {
27322   if (touches == null) touches = sourceEvent().touches;
27323
27324   for (var i = 0, n = touches ? touches.length : 0, points = new Array(n); i < n; ++i) {
27325     points[i] = point$5(node, touches[i]);
27326   }
27327
27328   return points;
27329 };
27330
27331 var emptyOn = dispatch("start", "end", "interrupt");
27332 var emptyTween = [];
27333
27334 var CREATED = 0;
27335 var SCHEDULED = 1;
27336 var STARTING = 2;
27337 var STARTED = 3;
27338 var RUNNING = 4;
27339 var ENDING = 5;
27340 var ENDED = 6;
27341
27342 var schedule = function(node, name, id, index, group, timing) {
27343   var schedules = node.__transition;
27344   if (!schedules) node.__transition = {};
27345   else if (id in schedules) return;
27346   create(node, id, {
27347     name: name,
27348     index: index, // For context during callback.
27349     group: group, // For context during callback.
27350     on: emptyOn,
27351     tween: emptyTween,
27352     time: timing.time,
27353     delay: timing.delay,
27354     duration: timing.duration,
27355     ease: timing.ease,
27356     timer: null,
27357     state: CREATED
27358   });
27359 };
27360
27361 function init(node, id) {
27362   var schedule = node.__transition;
27363   if (!schedule || !(schedule = schedule[id]) || schedule.state > CREATED) throw new Error("too late");
27364   return schedule;
27365 }
27366
27367 function set$3(node, id) {
27368   var schedule = node.__transition;
27369   if (!schedule || !(schedule = schedule[id]) || schedule.state > STARTING) throw new Error("too late");
27370   return schedule;
27371 }
27372
27373 function get$1(node, id) {
27374   var schedule = node.__transition;
27375   if (!schedule || !(schedule = schedule[id])) throw new Error("too late");
27376   return schedule;
27377 }
27378
27379 function create(node, id, self) {
27380   var schedules = node.__transition,
27381       tween;
27382
27383   // Initialize the self timer when the transition is created.
27384   // Note the actual delay is not known until the first callback!
27385   schedules[id] = self;
27386   self.timer = timer(schedule, 0, self.time);
27387
27388   function schedule(elapsed) {
27389     self.state = SCHEDULED;
27390     self.timer.restart(start, self.delay, self.time);
27391
27392     // If the elapsed delay is less than our first sleep, start immediately.
27393     if (self.delay <= elapsed) start(elapsed - self.delay);
27394   }
27395
27396   function start(elapsed) {
27397     var i, j, n, o;
27398
27399     // If the state is not SCHEDULED, then we previously errored on start.
27400     if (self.state !== SCHEDULED) return stop();
27401
27402     for (i in schedules) {
27403       o = schedules[i];
27404       if (o.name !== self.name) continue;
27405
27406       // While this element already has a starting transition during this frame,
27407       // defer starting an interrupting transition until that transition has a
27408       // chance to tick (and possibly end); see d3/d3-transition#54!
27409       if (o.state === STARTED) return timeout$1(start);
27410
27411       // Interrupt the active transition, if any.
27412       // Dispatch the interrupt event.
27413       if (o.state === RUNNING) {
27414         o.state = ENDED;
27415         o.timer.stop();
27416         o.on.call("interrupt", node, node.__data__, o.index, o.group);
27417         delete schedules[i];
27418       }
27419
27420       // Cancel any pre-empted transitions. No interrupt event is dispatched
27421       // because the cancelled transitions never started. Note that this also
27422       // removes this transition from the pending list!
27423       else if (+i < id) {
27424         o.state = ENDED;
27425         o.timer.stop();
27426         delete schedules[i];
27427       }
27428     }
27429
27430     // Defer the first tick to end of the current frame; see d3/d3#1576.
27431     // Note the transition may be canceled after start and before the first tick!
27432     // Note this must be scheduled before the start event; see d3/d3-transition#16!
27433     // Assuming this is successful, subsequent callbacks go straight to tick.
27434     timeout$1(function() {
27435       if (self.state === STARTED) {
27436         self.state = RUNNING;
27437         self.timer.restart(tick, self.delay, self.time);
27438         tick(elapsed);
27439       }
27440     });
27441
27442     // Dispatch the start event.
27443     // Note this must be done before the tween are initialized.
27444     self.state = STARTING;
27445     self.on.call("start", node, node.__data__, self.index, self.group);
27446     if (self.state !== STARTING) return; // interrupted
27447     self.state = STARTED;
27448
27449     // Initialize the tween, deleting null tween.
27450     tween = new Array(n = self.tween.length);
27451     for (i = 0, j = -1; i < n; ++i) {
27452       if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) {
27453         tween[++j] = o;
27454       }
27455     }
27456     tween.length = j + 1;
27457   }
27458
27459   function tick(elapsed) {
27460     var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1),
27461         i = -1,
27462         n = tween.length;
27463
27464     while (++i < n) {
27465       tween[i].call(null, t);
27466     }
27467
27468     // Dispatch the end event.
27469     if (self.state === ENDING) {
27470       self.on.call("end", node, node.__data__, self.index, self.group);
27471       stop();
27472     }
27473   }
27474
27475   function stop() {
27476     self.state = ENDED;
27477     self.timer.stop();
27478     delete schedules[id];
27479     for (var i in schedules) return; // eslint-disable-line no-unused-vars
27480     delete node.__transition;
27481   }
27482 }
27483
27484 var interrupt = function(node, name) {
27485   var schedules = node.__transition,
27486       schedule,
27487       active,
27488       empty = true,
27489       i;
27490
27491   if (!schedules) return;
27492
27493   name = name == null ? null : name + "";
27494
27495   for (i in schedules) {
27496     if ((schedule = schedules[i]).name !== name) { empty = false; continue; }
27497     active = schedule.state > STARTING && schedule.state < ENDING;
27498     schedule.state = ENDED;
27499     schedule.timer.stop();
27500     if (active) schedule.on.call("interrupt", node, node.__data__, schedule.index, schedule.group);
27501     delete schedules[i];
27502   }
27503
27504   if (empty) delete node.__transition;
27505 };
27506
27507 var selection_interrupt = function(name) {
27508   return this.each(function() {
27509     interrupt(this, name);
27510   });
27511 };
27512
27513 function tweenRemove(id, name) {
27514   var tween0, tween1;
27515   return function() {
27516     var schedule = set$3(this, id),
27517         tween = schedule.tween;
27518
27519     // If this node shared tween with the previous node,
27520     // just assign the updated shared tween and we’re done!
27521     // Otherwise, copy-on-write.
27522     if (tween !== tween0) {
27523       tween1 = tween0 = tween;
27524       for (var i = 0, n = tween1.length; i < n; ++i) {
27525         if (tween1[i].name === name) {
27526           tween1 = tween1.slice();
27527           tween1.splice(i, 1);
27528           break;
27529         }
27530       }
27531     }
27532
27533     schedule.tween = tween1;
27534   };
27535 }
27536
27537 function tweenFunction(id, name, value) {
27538   var tween0, tween1;
27539   if (typeof value !== "function") throw new Error;
27540   return function() {
27541     var schedule = set$3(this, id),
27542         tween = schedule.tween;
27543
27544     // If this node shared tween with the previous node,
27545     // just assign the updated shared tween and we’re done!
27546     // Otherwise, copy-on-write.
27547     if (tween !== tween0) {
27548       tween1 = (tween0 = tween).slice();
27549       for (var t = {name: name, value: value}, i = 0, n = tween1.length; i < n; ++i) {
27550         if (tween1[i].name === name) {
27551           tween1[i] = t;
27552           break;
27553         }
27554       }
27555       if (i === n) tween1.push(t);
27556     }
27557
27558     schedule.tween = tween1;
27559   };
27560 }
27561
27562 var transition_tween = function(name, value) {
27563   var id = this._id;
27564
27565   name += "";
27566
27567   if (arguments.length < 2) {
27568     var tween = get$1(this.node(), id).tween;
27569     for (var i = 0, n = tween.length, t; i < n; ++i) {
27570       if ((t = tween[i]).name === name) {
27571         return t.value;
27572       }
27573     }
27574     return null;
27575   }
27576
27577   return this.each((value == null ? tweenRemove : tweenFunction)(id, name, value));
27578 };
27579
27580 function tweenValue(transition, name, value) {
27581   var id = transition._id;
27582
27583   transition.each(function() {
27584     var schedule = set$3(this, id);
27585     (schedule.value || (schedule.value = {}))[name] = value.apply(this, arguments);
27586   });
27587
27588   return function(node) {
27589     return get$1(node, id).value[name];
27590   };
27591 }
27592
27593 var interpolate$1 = function(a, b) {
27594   var c;
27595   return (typeof b === "number" ? interpolateNumber
27596       : b instanceof color ? interpolateRgb
27597       : (c = color(b)) ? (b = c, interpolateRgb)
27598       : interpolateString)(a, b);
27599 };
27600
27601 function attrRemove$1(name) {
27602   return function() {
27603     this.removeAttribute(name);
27604   };
27605 }
27606
27607 function attrRemoveNS$1(fullname) {
27608   return function() {
27609     this.removeAttributeNS(fullname.space, fullname.local);
27610   };
27611 }
27612
27613 function attrConstant$1(name, interpolate$$1, value1) {
27614   var value00,
27615       interpolate0;
27616   return function() {
27617     var value0 = this.getAttribute(name);
27618     return value0 === value1 ? null
27619         : value0 === value00 ? interpolate0
27620         : interpolate0 = interpolate$$1(value00 = value0, value1);
27621   };
27622 }
27623
27624 function attrConstantNS$1(fullname, interpolate$$1, value1) {
27625   var value00,
27626       interpolate0;
27627   return function() {
27628     var value0 = this.getAttributeNS(fullname.space, fullname.local);
27629     return value0 === value1 ? null
27630         : value0 === value00 ? interpolate0
27631         : interpolate0 = interpolate$$1(value00 = value0, value1);
27632   };
27633 }
27634
27635 function attrFunction$1(name, interpolate$$1, value) {
27636   var value00,
27637       value10,
27638       interpolate0;
27639   return function() {
27640     var value0, value1 = value(this);
27641     if (value1 == null) return void this.removeAttribute(name);
27642     value0 = this.getAttribute(name);
27643     return value0 === value1 ? null
27644         : value0 === value00 && value1 === value10 ? interpolate0
27645         : interpolate0 = interpolate$$1(value00 = value0, value10 = value1);
27646   };
27647 }
27648
27649 function attrFunctionNS$1(fullname, interpolate$$1, value) {
27650   var value00,
27651       value10,
27652       interpolate0;
27653   return function() {
27654     var value0, value1 = value(this);
27655     if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local);
27656     value0 = this.getAttributeNS(fullname.space, fullname.local);
27657     return value0 === value1 ? null
27658         : value0 === value00 && value1 === value10 ? interpolate0
27659         : interpolate0 = interpolate$$1(value00 = value0, value10 = value1);
27660   };
27661 }
27662
27663 var transition_attr = function(name, value) {
27664   var fullname = namespace(name), i = fullname === "transform" ? interpolateTransformSvg : interpolate$1;
27665   return this.attrTween(name, typeof value === "function"
27666       ? (fullname.local ? attrFunctionNS$1 : attrFunction$1)(fullname, i, tweenValue(this, "attr." + name, value))
27667       : value == null ? (fullname.local ? attrRemoveNS$1 : attrRemove$1)(fullname)
27668       : (fullname.local ? attrConstantNS$1 : attrConstant$1)(fullname, i, value));
27669 };
27670
27671 function attrTweenNS(fullname, value) {
27672   function tween() {
27673     var node = this, i = value.apply(node, arguments);
27674     return i && function(t) {
27675       node.setAttributeNS(fullname.space, fullname.local, i(t));
27676     };
27677   }
27678   tween._value = value;
27679   return tween;
27680 }
27681
27682 function attrTween(name, value) {
27683   function tween() {
27684     var node = this, i = value.apply(node, arguments);
27685     return i && function(t) {
27686       node.setAttribute(name, i(t));
27687     };
27688   }
27689   tween._value = value;
27690   return tween;
27691 }
27692
27693 var transition_attrTween = function(name, value) {
27694   var key = "attr." + name;
27695   if (arguments.length < 2) return (key = this.tween(key)) && key._value;
27696   if (value == null) return this.tween(key, null);
27697   if (typeof value !== "function") throw new Error;
27698   var fullname = namespace(name);
27699   return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value));
27700 };
27701
27702 function delayFunction(id, value) {
27703   return function() {
27704     init(this, id).delay = +value.apply(this, arguments);
27705   };
27706 }
27707
27708 function delayConstant(id, value) {
27709   return value = +value, function() {
27710     init(this, id).delay = value;
27711   };
27712 }
27713
27714 var transition_delay = function(value) {
27715   var id = this._id;
27716
27717   return arguments.length
27718       ? this.each((typeof value === "function"
27719           ? delayFunction
27720           : delayConstant)(id, value))
27721       : get$1(this.node(), id).delay;
27722 };
27723
27724 function durationFunction(id, value) {
27725   return function() {
27726     set$3(this, id).duration = +value.apply(this, arguments);
27727   };
27728 }
27729
27730 function durationConstant(id, value) {
27731   return value = +value, function() {
27732     set$3(this, id).duration = value;
27733   };
27734 }
27735
27736 var transition_duration = function(value) {
27737   var id = this._id;
27738
27739   return arguments.length
27740       ? this.each((typeof value === "function"
27741           ? durationFunction
27742           : durationConstant)(id, value))
27743       : get$1(this.node(), id).duration;
27744 };
27745
27746 function easeConstant(id, value) {
27747   if (typeof value !== "function") throw new Error;
27748   return function() {
27749     set$3(this, id).ease = value;
27750   };
27751 }
27752
27753 var transition_ease = function(value) {
27754   var id = this._id;
27755
27756   return arguments.length
27757       ? this.each(easeConstant(id, value))
27758       : get$1(this.node(), id).ease;
27759 };
27760
27761 var transition_filter = function(match) {
27762   if (typeof match !== "function") match = matcher$1(match);
27763
27764   for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
27765     for (var group = groups[j], n = group.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {
27766       if ((node = group[i]) && match.call(node, node.__data__, i, group)) {
27767         subgroup.push(node);
27768       }
27769     }
27770   }
27771
27772   return new Transition(subgroups, this._parents, this._name, this._id);
27773 };
27774
27775 var transition_merge = function(transition) {
27776   if (transition._id !== this._id) throw new Error;
27777
27778   for (var groups0 = this._groups, groups1 = transition._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) {
27779     for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge = merges[j] = new Array(n), node, i = 0; i < n; ++i) {
27780       if (node = group0[i] || group1[i]) {
27781         merge[i] = node;
27782       }
27783     }
27784   }
27785
27786   for (; j < m0; ++j) {
27787     merges[j] = groups0[j];
27788   }
27789
27790   return new Transition(merges, this._parents, this._name, this._id);
27791 };
27792
27793 function start$1(name) {
27794   return (name + "").trim().split(/^|\s+/).every(function(t) {
27795     var i = t.indexOf(".");
27796     if (i >= 0) t = t.slice(0, i);
27797     return !t || t === "start";
27798   });
27799 }
27800
27801 function onFunction(id, name, listener) {
27802   var on0, on1, sit = start$1(name) ? init : set$3;
27803   return function() {
27804     var schedule = sit(this, id),
27805         on = schedule.on;
27806
27807     // If this node shared a dispatch with the previous node,
27808     // just assign the updated shared dispatch and we’re done!
27809     // Otherwise, copy-on-write.
27810     if (on !== on0) (on1 = (on0 = on).copy()).on(name, listener);
27811
27812     schedule.on = on1;
27813   };
27814 }
27815
27816 var transition_on = function(name, listener) {
27817   var id = this._id;
27818
27819   return arguments.length < 2
27820       ? get$1(this.node(), id).on.on(name)
27821       : this.each(onFunction(id, name, listener));
27822 };
27823
27824 function removeFunction(id) {
27825   return function() {
27826     var parent = this.parentNode;
27827     for (var i in this.__transition) if (+i !== id) return;
27828     if (parent) parent.removeChild(this);
27829   };
27830 }
27831
27832 var transition_remove = function() {
27833   return this.on("end.remove", removeFunction(this._id));
27834 };
27835
27836 var transition_select = function(select$$1) {
27837   var name = this._name,
27838       id = this._id;
27839
27840   if (typeof select$$1 !== "function") select$$1 = selector(select$$1);
27841
27842   for (var groups = this._groups, m = groups.length, subgroups = new Array(m), j = 0; j < m; ++j) {
27843     for (var group = groups[j], n = group.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {
27844       if ((node = group[i]) && (subnode = select$$1.call(node, node.__data__, i, group))) {
27845         if ("__data__" in node) subnode.__data__ = node.__data__;
27846         subgroup[i] = subnode;
27847         schedule(subgroup[i], name, id, i, subgroup, get$1(node, id));
27848       }
27849     }
27850   }
27851
27852   return new Transition(subgroups, this._parents, name, id);
27853 };
27854
27855 var transition_selectAll = function(select$$1) {
27856   var name = this._name,
27857       id = this._id;
27858
27859   if (typeof select$$1 !== "function") select$$1 = selectorAll(select$$1);
27860
27861   for (var groups = this._groups, m = groups.length, subgroups = [], parents = [], j = 0; j < m; ++j) {
27862     for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
27863       if (node = group[i]) {
27864         for (var children = select$$1.call(node, node.__data__, i, group), child, inherit = get$1(node, id), k = 0, l = children.length; k < l; ++k) {
27865           if (child = children[k]) {
27866             schedule(child, name, id, k, children, inherit);
27867           }
27868         }
27869         subgroups.push(children);
27870         parents.push(node);
27871       }
27872     }
27873   }
27874
27875   return new Transition(subgroups, parents, name, id);
27876 };
27877
27878 var Selection$1 = selection.prototype.constructor;
27879
27880 var transition_selection = function() {
27881   return new Selection$1(this._groups, this._parents);
27882 };
27883
27884 function styleRemove$1(name, interpolate$$1) {
27885   var value00,
27886       value10,
27887       interpolate0;
27888   return function() {
27889     var style = window$1(this).getComputedStyle(this, null),
27890         value0 = style.getPropertyValue(name),
27891         value1 = (this.style.removeProperty(name), style.getPropertyValue(name));
27892     return value0 === value1 ? null
27893         : value0 === value00 && value1 === value10 ? interpolate0
27894         : interpolate0 = interpolate$$1(value00 = value0, value10 = value1);
27895   };
27896 }
27897
27898 function styleRemoveEnd(name) {
27899   return function() {
27900     this.style.removeProperty(name);
27901   };
27902 }
27903
27904 function styleConstant$1(name, interpolate$$1, value1) {
27905   var value00,
27906       interpolate0;
27907   return function() {
27908     var value0 = window$1(this).getComputedStyle(this, null).getPropertyValue(name);
27909     return value0 === value1 ? null
27910         : value0 === value00 ? interpolate0
27911         : interpolate0 = interpolate$$1(value00 = value0, value1);
27912   };
27913 }
27914
27915 function styleFunction$1(name, interpolate$$1, value) {
27916   var value00,
27917       value10,
27918       interpolate0;
27919   return function() {
27920     var style = window$1(this).getComputedStyle(this, null),
27921         value0 = style.getPropertyValue(name),
27922         value1 = value(this);
27923     if (value1 == null) value1 = (this.style.removeProperty(name), style.getPropertyValue(name));
27924     return value0 === value1 ? null
27925         : value0 === value00 && value1 === value10 ? interpolate0
27926         : interpolate0 = interpolate$$1(value00 = value0, value10 = value1);
27927   };
27928 }
27929
27930 var transition_style = function(name, value, priority) {
27931   var i = (name += "") === "transform" ? interpolateTransformCss : interpolate$1;
27932   return value == null ? this
27933           .styleTween(name, styleRemove$1(name, i))
27934           .on("end.style." + name, styleRemoveEnd(name))
27935       : this.styleTween(name, typeof value === "function"
27936           ? styleFunction$1(name, i, tweenValue(this, "style." + name, value))
27937           : styleConstant$1(name, i, value), priority);
27938 };
27939
27940 function styleTween(name, value, priority) {
27941   function tween() {
27942     var node = this, i = value.apply(node, arguments);
27943     return i && function(t) {
27944       node.style.setProperty(name, i(t), priority);
27945     };
27946   }
27947   tween._value = value;
27948   return tween;
27949 }
27950
27951 var transition_styleTween = function(name, value, priority) {
27952   var key = "style." + (name += "");
27953   if (arguments.length < 2) return (key = this.tween(key)) && key._value;
27954   if (value == null) return this.tween(key, null);
27955   if (typeof value !== "function") throw new Error;
27956   return this.tween(key, styleTween(name, value, priority == null ? "" : priority));
27957 };
27958
27959 function textConstant$1(value) {
27960   return function() {
27961     this.textContent = value;
27962   };
27963 }
27964
27965 function textFunction$1(value) {
27966   return function() {
27967     var value1 = value(this);
27968     this.textContent = value1 == null ? "" : value1;
27969   };
27970 }
27971
27972 var transition_text = function(value) {
27973   return this.tween("text", typeof value === "function"
27974       ? textFunction$1(tweenValue(this, "text", value))
27975       : textConstant$1(value == null ? "" : value + ""));
27976 };
27977
27978 var transition_transition = function() {
27979   var name = this._name,
27980       id0 = this._id,
27981       id1 = newId();
27982
27983   for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
27984     for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
27985       if (node = group[i]) {
27986         var inherit = get$1(node, id0);
27987         schedule(node, name, id1, i, group, {
27988           time: inherit.time + inherit.delay + inherit.duration,
27989           delay: 0,
27990           duration: inherit.duration,
27991           ease: inherit.ease
27992         });
27993       }
27994     }
27995   }
27996
27997   return new Transition(groups, this._parents, name, id1);
27998 };
27999
28000 var id = 0;
28001
28002 function Transition(groups, parents, name, id) {
28003   this._groups = groups;
28004   this._parents = parents;
28005   this._name = name;
28006   this._id = id;
28007 }
28008
28009 function transition(name) {
28010   return selection().transition(name);
28011 }
28012
28013 function newId() {
28014   return ++id;
28015 }
28016
28017 var selection_prototype = selection.prototype;
28018
28019 Transition.prototype = transition.prototype = {
28020   constructor: Transition,
28021   select: transition_select,
28022   selectAll: transition_selectAll,
28023   filter: transition_filter,
28024   merge: transition_merge,
28025   selection: transition_selection,
28026   transition: transition_transition,
28027   call: selection_prototype.call,
28028   nodes: selection_prototype.nodes,
28029   node: selection_prototype.node,
28030   size: selection_prototype.size,
28031   empty: selection_prototype.empty,
28032   each: selection_prototype.each,
28033   on: transition_on,
28034   attr: transition_attr,
28035   attrTween: transition_attrTween,
28036   style: transition_style,
28037   styleTween: transition_styleTween,
28038   text: transition_text,
28039   remove: transition_remove,
28040   tween: transition_tween,
28041   delay: transition_delay,
28042   duration: transition_duration,
28043   ease: transition_ease
28044 };
28045
28046 var defaultTiming = {
28047   time: null, // Set on use.
28048   delay: 0,
28049   duration: 250,
28050   ease: cubicInOut
28051 };
28052
28053 function inherit(node, id) {
28054   var timing;
28055   while (!(timing = node.__transition) || !(timing = timing[id])) {
28056     if (!(node = node.parentNode)) {
28057       return defaultTiming.time = now(), defaultTiming;
28058     }
28059   }
28060   return timing;
28061 }
28062
28063 var selection_transition = function(name) {
28064   var id,
28065       timing;
28066
28067   if (name instanceof Transition) {
28068     id = name._id, name = name._name;
28069   } else {
28070     id = newId(), (timing = defaultTiming).time = now(), name = name == null ? null : name + "";
28071   }
28072
28073   for (var groups = this._groups, m = groups.length, j = 0; j < m; ++j) {
28074     for (var group = groups[j], n = group.length, node, i = 0; i < n; ++i) {
28075       if (node = group[i]) {
28076         schedule(node, name, id, i, group, timing || inherit(node, id));
28077       }
28078     }
28079   }
28080
28081   return new Transition(groups, this._parents, name, id);
28082 };
28083
28084 selection.prototype.interrupt = selection_interrupt;
28085 selection.prototype.transition = selection_transition;
28086
28087 var root$1 = [null];
28088
28089 var active = function(node, name) {
28090   var schedules = node.__transition,
28091       schedule,
28092       i;
28093
28094   if (schedules) {
28095     name = name == null ? null : name + "";
28096     for (i in schedules) {
28097       if ((schedule = schedules[i]).state > SCHEDULED && schedule.name === name) {
28098         return new Transition([[node]], root$1, name, +i);
28099       }
28100     }
28101   }
28102
28103   return null;
28104 };
28105
28106 var slice$4 = Array.prototype.slice;
28107
28108 var identity$5 = function(x) {
28109   return x;
28110 };
28111
28112 var top = 1;
28113 var right = 2;
28114 var bottom = 3;
28115 var left = 4;
28116 var epsilon$2 = 1e-6;
28117
28118 function translateX(scale0, scale1, d) {
28119   var x = scale0(d);
28120   return "translate(" + (isFinite(x) ? x : scale1(d)) + ",0)";
28121 }
28122
28123 function translateY(scale0, scale1, d) {
28124   var y = scale0(d);
28125   return "translate(0," + (isFinite(y) ? y : scale1(d)) + ")";
28126 }
28127
28128 function center(scale) {
28129   var offset = scale.bandwidth() / 2;
28130   if (scale.round()) offset = Math.round(offset);
28131   return function(d) {
28132     return scale(d) + offset;
28133   };
28134 }
28135
28136 function entering() {
28137   return !this.__axis;
28138 }
28139
28140 function axis(orient, scale) {
28141   var tickArguments = [],
28142       tickValues = null,
28143       tickFormat = null,
28144       tickSizeInner = 6,
28145       tickSizeOuter = 6,
28146       tickPadding = 3;
28147
28148   function axis(context) {
28149     var values = tickValues == null ? (scale.ticks ? scale.ticks.apply(scale, tickArguments) : scale.domain()) : tickValues,
28150         format = tickFormat == null ? (scale.tickFormat ? scale.tickFormat.apply(scale, tickArguments) : identity$5) : tickFormat,
28151         spacing = Math.max(tickSizeInner, 0) + tickPadding,
28152         transform = orient === top || orient === bottom ? translateX : translateY,
28153         range = scale.range(),
28154         range0 = range[0] + 0.5,
28155         range1 = range[range.length - 1] + 0.5,
28156         position = (scale.bandwidth ? center : identity$5)(scale.copy()),
28157         selection = context.selection ? context.selection() : context,
28158         path = selection.selectAll(".domain").data([null]),
28159         tick = selection.selectAll(".tick").data(values, scale).order(),
28160         tickExit = tick.exit(),
28161         tickEnter = tick.enter().append("g").attr("class", "tick"),
28162         line = tick.select("line"),
28163         text = tick.select("text"),
28164         k = orient === top || orient === left ? -1 : 1,
28165         x, y = orient === left || orient === right ? (x = "x", "y") : (x = "y", "x");
28166
28167     path = path.merge(path.enter().insert("path", ".tick")
28168         .attr("class", "domain")
28169         .attr("stroke", "#000"));
28170
28171     tick = tick.merge(tickEnter);
28172
28173     line = line.merge(tickEnter.append("line")
28174         .attr("stroke", "#000")
28175         .attr(x + "2", k * tickSizeInner)
28176         .attr(y + "1", 0.5)
28177         .attr(y + "2", 0.5));
28178
28179     text = text.merge(tickEnter.append("text")
28180         .attr("fill", "#000")
28181         .attr(x, k * spacing)
28182         .attr(y, 0.5)
28183         .attr("dy", orient === top ? "0em" : orient === bottom ? "0.71em" : "0.32em"));
28184
28185     if (context !== selection) {
28186       path = path.transition(context);
28187       tick = tick.transition(context);
28188       line = line.transition(context);
28189       text = text.transition(context);
28190
28191       tickExit = tickExit.transition(context)
28192           .attr("opacity", epsilon$2)
28193           .attr("transform", function(d) { return transform(position, this.parentNode.__axis || position, d); });
28194
28195       tickEnter
28196           .attr("opacity", epsilon$2)
28197           .attr("transform", function(d) { return transform(this.parentNode.__axis || position, position, d); });
28198     }
28199
28200     tickExit.remove();
28201
28202     path
28203         .attr("d", orient === left || orient == right
28204             ? "M" + k * tickSizeOuter + "," + range0 + "H0.5V" + range1 + "H" + k * tickSizeOuter
28205             : "M" + range0 + "," + k * tickSizeOuter + "V0.5H" + range1 + "V" + k * tickSizeOuter);
28206
28207     tick
28208         .attr("opacity", 1)
28209         .attr("transform", function(d) { return transform(position, position, d); });
28210
28211     line
28212         .attr(x + "2", k * tickSizeInner);
28213
28214     text
28215         .attr(x, k * spacing)
28216         .text(format);
28217
28218     selection.filter(entering)
28219         .attr("fill", "none")
28220         .attr("font-size", 10)
28221         .attr("font-family", "sans-serif")
28222         .attr("text-anchor", orient === right ? "start" : orient === left ? "end" : "middle");
28223
28224     selection
28225         .each(function() { this.__axis = position; });
28226   }
28227
28228   axis.scale = function(_) {
28229     return arguments.length ? (scale = _, axis) : scale;
28230   };
28231
28232   axis.ticks = function() {
28233     return tickArguments = slice$4.call(arguments), axis;
28234   };
28235
28236   axis.tickArguments = function(_) {
28237     return arguments.length ? (tickArguments = _ == null ? [] : slice$4.call(_), axis) : tickArguments.slice();
28238   };
28239
28240   axis.tickValues = function(_) {
28241     return arguments.length ? (tickValues = _ == null ? null : slice$4.call(_), axis) : tickValues && tickValues.slice();
28242   };
28243
28244   axis.tickFormat = function(_) {
28245     return arguments.length ? (tickFormat = _, axis) : tickFormat;
28246   };
28247
28248   axis.tickSize = function(_) {
28249     return arguments.length ? (tickSizeInner = tickSizeOuter = +_, axis) : tickSizeInner;
28250   };
28251
28252   axis.tickSizeInner = function(_) {
28253     return arguments.length ? (tickSizeInner = +_, axis) : tickSizeInner;
28254   };
28255
28256   axis.tickSizeOuter = function(_) {
28257     return arguments.length ? (tickSizeOuter = +_, axis) : tickSizeOuter;
28258   };
28259
28260   axis.tickPadding = function(_) {
28261     return arguments.length ? (tickPadding = +_, axis) : tickPadding;
28262   };
28263
28264   return axis;
28265 }
28266
28267 function axisTop(scale) {
28268   return axis(top, scale);
28269 }
28270
28271 function axisRight(scale) {
28272   return axis(right, scale);
28273 }
28274
28275 function axisBottom(scale) {
28276   return axis(bottom, scale);
28277 }
28278
28279 function axisLeft(scale) {
28280   return axis(left, scale);
28281 }
28282
28283 function defaultSeparation(a, b) {
28284   return a.parent === b.parent ? 1 : 2;
28285 }
28286
28287 function meanX(children) {
28288   return children.reduce(meanXReduce, 0) / children.length;
28289 }
28290
28291 function meanXReduce(x, c) {
28292   return x + c.x;
28293 }
28294
28295 function maxY(children) {
28296   return 1 + children.reduce(maxYReduce, 0);
28297 }
28298
28299 function maxYReduce(y, c) {
28300   return Math.max(y, c.y);
28301 }
28302
28303 function leafLeft(node) {
28304   var children;
28305   while (children = node.children) node = children[0];
28306   return node;
28307 }
28308
28309 function leafRight(node) {
28310   var children;
28311   while (children = node.children) node = children[children.length - 1];
28312   return node;
28313 }
28314
28315 var cluster = function() {
28316   var separation = defaultSeparation,
28317       dx = 1,
28318       dy = 1,
28319       nodeSize = false;
28320
28321   function cluster(root) {
28322     var previousNode,
28323         x = 0;
28324
28325     // First walk, computing the initial x & y values.
28326     root.eachAfter(function(node) {
28327       var children = node.children;
28328       if (children) {
28329         node.x = meanX(children);
28330         node.y = maxY(children);
28331       } else {
28332         node.x = previousNode ? x += separation(node, previousNode) : 0;
28333         node.y = 0;
28334         previousNode = node;
28335       }
28336     });
28337
28338     var left = leafLeft(root),
28339         right = leafRight(root),
28340         x0 = left.x - separation(left, right) / 2,
28341         x1 = right.x + separation(right, left) / 2;
28342
28343     // Second walk, normalizing x & y to the desired size.
28344     return root.eachAfter(nodeSize ? function(node) {
28345       node.x = (node.x - root.x) * dx;
28346       node.y = (root.y - node.y) * dy;
28347     } : function(node) {
28348       node.x = (node.x - x0) / (x1 - x0) * dx;
28349       node.y = (1 - (root.y ? node.y / root.y : 1)) * dy;
28350     });
28351   }
28352
28353   cluster.separation = function(x) {
28354     return arguments.length ? (separation = x, cluster) : separation;
28355   };
28356
28357   cluster.size = function(x) {
28358     return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? null : [dx, dy]);
28359   };
28360
28361   cluster.nodeSize = function(x) {
28362     return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], cluster) : (nodeSize ? [dx, dy] : null);
28363   };
28364
28365   return cluster;
28366 };
28367
28368 var node_each = function(callback) {
28369   var node = this, current, next = [node], children, i, n;
28370   do {
28371     current = next.reverse(), next = [];
28372     while (node = current.pop()) {
28373       callback(node), children = node.children;
28374       if (children) for (i = 0, n = children.length; i < n; ++i) {
28375         next.push(children[i]);
28376       }
28377     }
28378   } while (next.length);
28379   return this;
28380 };
28381
28382 var node_eachBefore = function(callback) {
28383   var node = this, nodes = [node], children, i;
28384   while (node = nodes.pop()) {
28385     callback(node), children = node.children;
28386     if (children) for (i = children.length - 1; i >= 0; --i) {
28387       nodes.push(children[i]);
28388     }
28389   }
28390   return this;
28391 };
28392
28393 var node_eachAfter = function(callback) {
28394   var node = this, nodes = [node], next = [], children, i, n;
28395   while (node = nodes.pop()) {
28396     next.push(node), children = node.children;
28397     if (children) for (i = 0, n = children.length; i < n; ++i) {
28398       nodes.push(children[i]);
28399     }
28400   }
28401   while (node = next.pop()) {
28402     callback(node);
28403   }
28404   return this;
28405 };
28406
28407 var node_sum = function(value) {
28408   return this.eachAfter(function(node) {
28409     var sum = +value(node.data) || 0,
28410         children = node.children,
28411         i = children && children.length;
28412     while (--i >= 0) sum += children[i].value;
28413     node.value = sum;
28414   });
28415 };
28416
28417 var node_sort = function(compare) {
28418   return this.eachBefore(function(node) {
28419     if (node.children) {
28420       node.children.sort(compare);
28421     }
28422   });
28423 };
28424
28425 var node_path = function(end) {
28426   var start = this,
28427       ancestor = leastCommonAncestor(start, end),
28428       nodes = [start];
28429   while (start !== ancestor) {
28430     start = start.parent;
28431     nodes.push(start);
28432   }
28433   var k = nodes.length;
28434   while (end !== ancestor) {
28435     nodes.splice(k, 0, end);
28436     end = end.parent;
28437   }
28438   return nodes;
28439 };
28440
28441 function leastCommonAncestor(a, b) {
28442   if (a === b) return a;
28443   var aNodes = a.ancestors(),
28444       bNodes = b.ancestors(),
28445       c = null;
28446   a = aNodes.pop();
28447   b = bNodes.pop();
28448   while (a === b) {
28449     c = a;
28450     a = aNodes.pop();
28451     b = bNodes.pop();
28452   }
28453   return c;
28454 }
28455
28456 var node_ancestors = function() {
28457   var node = this, nodes = [node];
28458   while (node = node.parent) {
28459     nodes.push(node);
28460   }
28461   return nodes;
28462 };
28463
28464 var node_descendants = function() {
28465   var nodes = [];
28466   this.each(function(node) {
28467     nodes.push(node);
28468   });
28469   return nodes;
28470 };
28471
28472 var node_leaves = function() {
28473   var leaves = [];
28474   this.eachBefore(function(node) {
28475     if (!node.children) {
28476       leaves.push(node);
28477     }
28478   });
28479   return leaves;
28480 };
28481
28482 var node_links = function() {
28483   var root = this, links = [];
28484   root.each(function(node) {
28485     if (node !== root) { // Don’t include the root’s parent, if any.
28486       links.push({source: node.parent, target: node});
28487     }
28488   });
28489   return links;
28490 };
28491
28492 function hierarchy(data, children) {
28493   var root = new Node(data),
28494       valued = +data.value && (root.value = data.value),
28495       node,
28496       nodes = [root],
28497       child,
28498       childs,
28499       i,
28500       n;
28501
28502   if (children == null) children = defaultChildren;
28503
28504   while (node = nodes.pop()) {
28505     if (valued) node.value = +node.data.value;
28506     if ((childs = children(node.data)) && (n = childs.length)) {
28507       node.children = new Array(n);
28508       for (i = n - 1; i >= 0; --i) {
28509         nodes.push(child = node.children[i] = new Node(childs[i]));
28510         child.parent = node;
28511         child.depth = node.depth + 1;
28512       }
28513     }
28514   }
28515
28516   return root.eachBefore(computeHeight);
28517 }
28518
28519 function node_copy() {
28520   return hierarchy(this).eachBefore(copyData);
28521 }
28522
28523 function defaultChildren(d) {
28524   return d.children;
28525 }
28526
28527 function copyData(node) {
28528   node.data = node.data.data;
28529 }
28530
28531 function computeHeight(node) {
28532   var height = 0;
28533   do node.height = height;
28534   while ((node = node.parent) && (node.height < ++height));
28535 }
28536
28537 function Node(data) {
28538   this.data = data;
28539   this.depth =
28540   this.height = 0;
28541   this.parent = null;
28542 }
28543
28544 Node.prototype = hierarchy.prototype = {
28545   constructor: Node,
28546   each: node_each,
28547   eachAfter: node_eachAfter,
28548   eachBefore: node_eachBefore,
28549   sum: node_sum,
28550   sort: node_sort,
28551   path: node_path,
28552   ancestors: node_ancestors,
28553   descendants: node_descendants,
28554   leaves: node_leaves,
28555   links: node_links,
28556   copy: node_copy
28557 };
28558
28559 function Node$2(value) {
28560   this._ = value;
28561   this.next = null;
28562 }
28563
28564 var shuffle$1 = function(array) {
28565   var i,
28566       n = (array = array.slice()).length,
28567       head = null,
28568       node = head;
28569
28570   while (n) {
28571     var next = new Node$2(array[n - 1]);
28572     if (node) node = node.next = next;
28573     else node = head = next;
28574     array[i] = array[--n];
28575   }
28576
28577   return {
28578     head: head,
28579     tail: node
28580   };
28581 };
28582
28583 var enclose = function(circles) {
28584   return encloseN(shuffle$1(circles), []);
28585 };
28586
28587 function encloses(a, b) {
28588   var dx = b.x - a.x,
28589       dy = b.y - a.y,
28590       dr = a.r - b.r;
28591   return dr * dr + 1e-6 > dx * dx + dy * dy;
28592 }
28593
28594 // Returns the smallest circle that contains circles L and intersects circles B.
28595 function encloseN(L, B) {
28596   var circle,
28597       l0 = null,
28598       l1 = L.head,
28599       l2,
28600       p1;
28601
28602   switch (B.length) {
28603     case 1: circle = enclose1(B[0]); break;
28604     case 2: circle = enclose2(B[0], B[1]); break;
28605     case 3: circle = enclose3(B[0], B[1], B[2]); break;
28606   }
28607
28608   while (l1) {
28609     p1 = l1._, l2 = l1.next;
28610     if (!circle || !encloses(circle, p1)) {
28611
28612       // Temporarily truncate L before l1.
28613       if (l0) L.tail = l0, l0.next = null;
28614       else L.head = L.tail = null;
28615
28616       B.push(p1);
28617       circle = encloseN(L, B); // Note: reorders L!
28618       B.pop();
28619
28620       // Move l1 to the front of L and reconnect the truncated list L.
28621       if (L.head) l1.next = L.head, L.head = l1;
28622       else l1.next = null, L.head = L.tail = l1;
28623       l0 = L.tail, l0.next = l2;
28624
28625     } else {
28626       l0 = l1;
28627     }
28628     l1 = l2;
28629   }
28630
28631   L.tail = l0;
28632   return circle;
28633 }
28634
28635 function enclose1(a) {
28636   return {
28637     x: a.x,
28638     y: a.y,
28639     r: a.r
28640   };
28641 }
28642
28643 function enclose2(a, b) {
28644   var x1 = a.x, y1 = a.y, r1 = a.r,
28645       x2 = b.x, y2 = b.y, r2 = b.r,
28646       x21 = x2 - x1, y21 = y2 - y1, r21 = r2 - r1,
28647       l = Math.sqrt(x21 * x21 + y21 * y21);
28648   return {
28649     x: (x1 + x2 + x21 / l * r21) / 2,
28650     y: (y1 + y2 + y21 / l * r21) / 2,
28651     r: (l + r1 + r2) / 2
28652   };
28653 }
28654
28655 function enclose3(a, b, c) {
28656   var x1 = a.x, y1 = a.y, r1 = a.r,
28657       x2 = b.x, y2 = b.y, r2 = b.r,
28658       x3 = c.x, y3 = c.y, r3 = c.r,
28659       a2 = 2 * (x1 - x2),
28660       b2 = 2 * (y1 - y2),
28661       c2 = 2 * (r2 - r1),
28662       d2 = x1 * x1 + y1 * y1 - r1 * r1 - x2 * x2 - y2 * y2 + r2 * r2,
28663       a3 = 2 * (x1 - x3),
28664       b3 = 2 * (y1 - y3),
28665       c3 = 2 * (r3 - r1),
28666       d3 = x1 * x1 + y1 * y1 - r1 * r1 - x3 * x3 - y3 * y3 + r3 * r3,
28667       ab = a3 * b2 - a2 * b3,
28668       xa = (b2 * d3 - b3 * d2) / ab - x1,
28669       xb = (b3 * c2 - b2 * c3) / ab,
28670       ya = (a3 * d2 - a2 * d3) / ab - y1,
28671       yb = (a2 * c3 - a3 * c2) / ab,
28672       A = xb * xb + yb * yb - 1,
28673       B = 2 * (xa * xb + ya * yb + r1),
28674       C = xa * xa + ya * ya - r1 * r1,
28675       r = (-B - Math.sqrt(B * B - 4 * A * C)) / (2 * A);
28676   return {
28677     x: xa + xb * r + x1,
28678     y: ya + yb * r + y1,
28679     r: r
28680   };
28681 }
28682
28683 function place(a, b, c) {
28684   var ax = a.x,
28685       ay = a.y,
28686       da = b.r + c.r,
28687       db = a.r + c.r,
28688       dx = b.x - ax,
28689       dy = b.y - ay,
28690       dc = dx * dx + dy * dy;
28691   if (dc) {
28692     var x = 0.5 + ((db *= db) - (da *= da)) / (2 * dc),
28693         y = Math.sqrt(Math.max(0, 2 * da * (db + dc) - (db -= dc) * db - da * da)) / (2 * dc);
28694     c.x = ax + x * dx + y * dy;
28695     c.y = ay + x * dy - y * dx;
28696   } else {
28697     c.x = ax + db;
28698     c.y = ay;
28699   }
28700 }
28701
28702 function intersects(a, b) {
28703   var dx = b.x - a.x,
28704       dy = b.y - a.y,
28705       dr = a.r + b.r;
28706   return dr * dr > dx * dx + dy * dy;
28707 }
28708
28709 function distance2(circle, x, y) {
28710   var dx = circle.x - x,
28711       dy = circle.y - y;
28712   return dx * dx + dy * dy;
28713 }
28714
28715 function Node$1(circle) {
28716   this._ = circle;
28717   this.next = null;
28718   this.previous = null;
28719 }
28720
28721 function packEnclose(circles) {
28722   if (!(n = circles.length)) return 0;
28723
28724   var a, b, c, n;
28725
28726   // Place the first circle.
28727   a = circles[0], a.x = 0, a.y = 0;
28728   if (!(n > 1)) return a.r;
28729
28730   // Place the second circle.
28731   b = circles[1], a.x = -b.r, b.x = a.r, b.y = 0;
28732   if (!(n > 2)) return a.r + b.r;
28733
28734   // Place the third circle.
28735   place(b, a, c = circles[2]);
28736
28737   // Initialize the weighted centroid.
28738   var aa = a.r * a.r,
28739       ba = b.r * b.r,
28740       ca = c.r * c.r,
28741       oa = aa + ba + ca,
28742       ox = aa * a.x + ba * b.x + ca * c.x,
28743       oy = aa * a.y + ba * b.y + ca * c.y,
28744       cx, cy, i, j, k, sj, sk;
28745
28746   // Initialize the front-chain using the first three circles a, b and c.
28747   a = new Node$1(a), b = new Node$1(b), c = new Node$1(c);
28748   a.next = c.previous = b;
28749   b.next = a.previous = c;
28750   c.next = b.previous = a;
28751
28752   // Attempt to place each remaining circle…
28753   pack: for (i = 3; i < n; ++i) {
28754     place(a._, b._, c = circles[i]), c = new Node$1(c);
28755
28756     // If there are only three elements in the front-chain…
28757     if ((k = a.previous) === (j = b.next)) {
28758       // If the new circle intersects the third circle,
28759       // rotate the front chain to try the next position.
28760       if (intersects(j._, c._)) {
28761         a = b, b = j, --i;
28762         continue pack;
28763       }
28764     }
28765
28766     // Find the closest intersecting circle on the front-chain, if any.
28767     else {
28768       sj = j._.r, sk = k._.r;
28769       do {
28770         if (sj <= sk) {
28771           if (intersects(j._, c._)) {
28772             b = j, a.next = b, b.previous = a, --i;
28773             continue pack;
28774           }
28775           j = j.next, sj += j._.r;
28776         } else {
28777           if (intersects(k._, c._)) {
28778             a = k, a.next = b, b.previous = a, --i;
28779             continue pack;
28780           }
28781           k = k.previous, sk += k._.r;
28782         }
28783       } while (j !== k.next);
28784     }
28785
28786     // Success! Insert the new circle c between a and b.
28787     c.previous = a, c.next = b, a.next = b.previous = b = c;
28788
28789     // Update the weighted centroid.
28790     oa += ca = c._.r * c._.r;
28791     ox += ca * c._.x;
28792     oy += ca * c._.y;
28793
28794     // Compute the new closest circle a to centroid.
28795     aa = distance2(a._, cx = ox / oa, cy = oy / oa);
28796     while ((c = c.next) !== b) {
28797       if ((ca = distance2(c._, cx, cy)) < aa) {
28798         a = c, aa = ca;
28799       }
28800     }
28801     b = a.next;
28802   }
28803
28804   // Compute the enclosing circle of the front chain.
28805   a = [b._], c = b; while ((c = c.next) !== b) a.push(c._); c = enclose(a);
28806
28807   // Translate the circles to put the enclosing circle around the origin.
28808   for (i = 0; i < n; ++i) a = circles[i], a.x -= c.x, a.y -= c.y;
28809
28810   return c.r;
28811 }
28812
28813 var siblings = function(circles) {
28814   packEnclose(circles);
28815   return circles;
28816 };
28817
28818 function optional(f) {
28819   return f == null ? null : required(f);
28820 }
28821
28822 function required(f) {
28823   if (typeof f !== "function") throw new Error;
28824   return f;
28825 }
28826
28827 function constantZero() {
28828   return 0;
28829 }
28830
28831 var constant$6 = function(x) {
28832   return function() {
28833     return x;
28834   };
28835 };
28836
28837 function defaultRadius(d) {
28838   return Math.sqrt(d.value);
28839 }
28840
28841 var index$2 = function() {
28842   var radius = null,
28843       dx = 1,
28844       dy = 1,
28845       padding = constantZero;
28846
28847   function pack(root) {
28848     root.x = dx / 2, root.y = dy / 2;
28849     if (radius) {
28850       root.eachBefore(radiusLeaf(radius))
28851           .eachAfter(packChildren(padding, 0.5))
28852           .eachBefore(translateChild(1));
28853     } else {
28854       root.eachBefore(radiusLeaf(defaultRadius))
28855           .eachAfter(packChildren(constantZero, 1))
28856           .eachAfter(packChildren(padding, root.r / Math.min(dx, dy)))
28857           .eachBefore(translateChild(Math.min(dx, dy) / (2 * root.r)));
28858     }
28859     return root;
28860   }
28861
28862   pack.radius = function(x) {
28863     return arguments.length ? (radius = optional(x), pack) : radius;
28864   };
28865
28866   pack.size = function(x) {
28867     return arguments.length ? (dx = +x[0], dy = +x[1], pack) : [dx, dy];
28868   };
28869
28870   pack.padding = function(x) {
28871     return arguments.length ? (padding = typeof x === "function" ? x : constant$6(+x), pack) : padding;
28872   };
28873
28874   return pack;
28875 };
28876
28877 function radiusLeaf(radius) {
28878   return function(node) {
28879     if (!node.children) {
28880       node.r = Math.max(0, +radius(node) || 0);
28881     }
28882   };
28883 }
28884
28885 function packChildren(padding, k) {
28886   return function(node) {
28887     if (children = node.children) {
28888       var children,
28889           i,
28890           n = children.length,
28891           r = padding(node) * k || 0,
28892           e;
28893
28894       if (r) for (i = 0; i < n; ++i) children[i].r += r;
28895       e = packEnclose(children);
28896       if (r) for (i = 0; i < n; ++i) children[i].r -= r;
28897       node.r = e + r;
28898     }
28899   };
28900 }
28901
28902 function translateChild(k) {
28903   return function(node) {
28904     var parent = node.parent;
28905     node.r *= k;
28906     if (parent) {
28907       node.x = parent.x + k * node.x;
28908       node.y = parent.y + k * node.y;
28909     }
28910   };
28911 }
28912
28913 var roundNode = function(node) {
28914   node.x0 = Math.round(node.x0);
28915   node.y0 = Math.round(node.y0);
28916   node.x1 = Math.round(node.x1);
28917   node.y1 = Math.round(node.y1);
28918 };
28919
28920 var treemapDice = function(parent, x0, y0, x1, y1) {
28921   var nodes = parent.children,
28922       node,
28923       i = -1,
28924       n = nodes.length,
28925       k = parent.value && (x1 - x0) / parent.value;
28926
28927   while (++i < n) {
28928     node = nodes[i], node.y0 = y0, node.y1 = y1;
28929     node.x0 = x0, node.x1 = x0 += node.value * k;
28930   }
28931 };
28932
28933 var partition = function() {
28934   var dx = 1,
28935       dy = 1,
28936       padding = 0,
28937       round = false;
28938
28939   function partition(root) {
28940     var n = root.height + 1;
28941     root.x0 =
28942     root.y0 = padding;
28943     root.x1 = dx;
28944     root.y1 = dy / n;
28945     root.eachBefore(positionNode(dy, n));
28946     if (round) root.eachBefore(roundNode);
28947     return root;
28948   }
28949
28950   function positionNode(dy, n) {
28951     return function(node) {
28952       if (node.children) {
28953         treemapDice(node, node.x0, dy * (node.depth + 1) / n, node.x1, dy * (node.depth + 2) / n);
28954       }
28955       var x0 = node.x0,
28956           y0 = node.y0,
28957           x1 = node.x1 - padding,
28958           y1 = node.y1 - padding;
28959       if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
28960       if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
28961       node.x0 = x0;
28962       node.y0 = y0;
28963       node.x1 = x1;
28964       node.y1 = y1;
28965     };
28966   }
28967
28968   partition.round = function(x) {
28969     return arguments.length ? (round = !!x, partition) : round;
28970   };
28971
28972   partition.size = function(x) {
28973     return arguments.length ? (dx = +x[0], dy = +x[1], partition) : [dx, dy];
28974   };
28975
28976   partition.padding = function(x) {
28977     return arguments.length ? (padding = +x, partition) : padding;
28978   };
28979
28980   return partition;
28981 };
28982
28983 var keyPrefix$1 = "$";
28984 var preroot = {depth: -1};
28985 var ambiguous = {};
28986
28987 function defaultId(d) {
28988   return d.id;
28989 }
28990
28991 function defaultParentId(d) {
28992   return d.parentId;
28993 }
28994
28995 var stratify = function() {
28996   var id = defaultId,
28997       parentId = defaultParentId;
28998
28999   function stratify(data) {
29000     var d,
29001         i,
29002         n = data.length,
29003         root,
29004         parent,
29005         node,
29006         nodes = new Array(n),
29007         nodeId,
29008         nodeKey,
29009         nodeByKey = {};
29010
29011     for (i = 0; i < n; ++i) {
29012       d = data[i], node = nodes[i] = new Node(d);
29013       if ((nodeId = id(d, i, data)) != null && (nodeId += "")) {
29014         nodeKey = keyPrefix$1 + (node.id = nodeId);
29015         nodeByKey[nodeKey] = nodeKey in nodeByKey ? ambiguous : node;
29016       }
29017     }
29018
29019     for (i = 0; i < n; ++i) {
29020       node = nodes[i], nodeId = parentId(data[i], i, data);
29021       if (nodeId == null || !(nodeId += "")) {
29022         if (root) throw new Error("multiple roots");
29023         root = node;
29024       } else {
29025         parent = nodeByKey[keyPrefix$1 + nodeId];
29026         if (!parent) throw new Error("missing: " + nodeId);
29027         if (parent === ambiguous) throw new Error("ambiguous: " + nodeId);
29028         if (parent.children) parent.children.push(node);
29029         else parent.children = [node];
29030         node.parent = parent;
29031       }
29032     }
29033
29034     if (!root) throw new Error("no root");
29035     root.parent = preroot;
29036     root.eachBefore(function(node) { node.depth = node.parent.depth + 1; --n; }).eachBefore(computeHeight);
29037     root.parent = null;
29038     if (n > 0) throw new Error("cycle");
29039
29040     return root;
29041   }
29042
29043   stratify.id = function(x) {
29044     return arguments.length ? (id = required(x), stratify) : id;
29045   };
29046
29047   stratify.parentId = function(x) {
29048     return arguments.length ? (parentId = required(x), stratify) : parentId;
29049   };
29050
29051   return stratify;
29052 };
29053
29054 function defaultSeparation$1(a, b) {
29055   return a.parent === b.parent ? 1 : 2;
29056 }
29057
29058 // function radialSeparation(a, b) {
29059 //   return (a.parent === b.parent ? 1 : 2) / a.depth;
29060 // }
29061
29062 // This function is used to traverse the left contour of a subtree (or
29063 // subforest). It returns the successor of v on this contour. This successor is
29064 // either given by the leftmost child of v or by the thread of v. The function
29065 // returns null if and only if v is on the highest level of its subtree.
29066 function nextLeft(v) {
29067   var children = v.children;
29068   return children ? children[0] : v.t;
29069 }
29070
29071 // This function works analogously to nextLeft.
29072 function nextRight(v) {
29073   var children = v.children;
29074   return children ? children[children.length - 1] : v.t;
29075 }
29076
29077 // Shifts the current subtree rooted at w+. This is done by increasing
29078 // prelim(w+) and mod(w+) by shift.
29079 function moveSubtree(wm, wp, shift) {
29080   var change = shift / (wp.i - wm.i);
29081   wp.c -= change;
29082   wp.s += shift;
29083   wm.c += change;
29084   wp.z += shift;
29085   wp.m += shift;
29086 }
29087
29088 // All other shifts, applied to the smaller subtrees between w- and w+, are
29089 // performed by this function. To prepare the shifts, we have to adjust
29090 // change(w+), shift(w+), and change(w-).
29091 function executeShifts(v) {
29092   var shift = 0,
29093       change = 0,
29094       children = v.children,
29095       i = children.length,
29096       w;
29097   while (--i >= 0) {
29098     w = children[i];
29099     w.z += shift;
29100     w.m += shift;
29101     shift += w.s + (change += w.c);
29102   }
29103 }
29104
29105 // If vi-’s ancestor is a sibling of v, returns vi-’s ancestor. Otherwise,
29106 // returns the specified (default) ancestor.
29107 function nextAncestor(vim, v, ancestor) {
29108   return vim.a.parent === v.parent ? vim.a : ancestor;
29109 }
29110
29111 function TreeNode(node, i) {
29112   this._ = node;
29113   this.parent = null;
29114   this.children = null;
29115   this.A = null; // default ancestor
29116   this.a = this; // ancestor
29117   this.z = 0; // prelim
29118   this.m = 0; // mod
29119   this.c = 0; // change
29120   this.s = 0; // shift
29121   this.t = null; // thread
29122   this.i = i; // number
29123 }
29124
29125 TreeNode.prototype = Object.create(Node.prototype);
29126
29127 function treeRoot(root) {
29128   var tree = new TreeNode(root, 0),
29129       node,
29130       nodes = [tree],
29131       child,
29132       children,
29133       i,
29134       n;
29135
29136   while (node = nodes.pop()) {
29137     if (children = node._.children) {
29138       node.children = new Array(n = children.length);
29139       for (i = n - 1; i >= 0; --i) {
29140         nodes.push(child = node.children[i] = new TreeNode(children[i], i));
29141         child.parent = node;
29142       }
29143     }
29144   }
29145
29146   (tree.parent = new TreeNode(null, 0)).children = [tree];
29147   return tree;
29148 }
29149
29150 // Node-link tree diagram using the Reingold-Tilford "tidy" algorithm
29151 var tree = function() {
29152   var separation = defaultSeparation$1,
29153       dx = 1,
29154       dy = 1,
29155       nodeSize = null;
29156
29157   function tree(root) {
29158     var t = treeRoot(root);
29159
29160     // Compute the layout using Buchheim et al.’s algorithm.
29161     t.eachAfter(firstWalk), t.parent.m = -t.z;
29162     t.eachBefore(secondWalk);
29163
29164     // If a fixed node size is specified, scale x and y.
29165     if (nodeSize) root.eachBefore(sizeNode);
29166
29167     // If a fixed tree size is specified, scale x and y based on the extent.
29168     // Compute the left-most, right-most, and depth-most nodes for extents.
29169     else {
29170       var left = root,
29171           right = root,
29172           bottom = root;
29173       root.eachBefore(function(node) {
29174         if (node.x < left.x) left = node;
29175         if (node.x > right.x) right = node;
29176         if (node.depth > bottom.depth) bottom = node;
29177       });
29178       var s = left === right ? 1 : separation(left, right) / 2,
29179           tx = s - left.x,
29180           kx = dx / (right.x + s + tx),
29181           ky = dy / (bottom.depth || 1);
29182       root.eachBefore(function(node) {
29183         node.x = (node.x + tx) * kx;
29184         node.y = node.depth * ky;
29185       });
29186     }
29187
29188     return root;
29189   }
29190
29191   // Computes a preliminary x-coordinate for v. Before that, FIRST WALK is
29192   // applied recursively to the children of v, as well as the function
29193   // APPORTION. After spacing out the children by calling EXECUTE SHIFTS, the
29194   // node v is placed to the midpoint of its outermost children.
29195   function firstWalk(v) {
29196     var children = v.children,
29197         siblings = v.parent.children,
29198         w = v.i ? siblings[v.i - 1] : null;
29199     if (children) {
29200       executeShifts(v);
29201       var midpoint = (children[0].z + children[children.length - 1].z) / 2;
29202       if (w) {
29203         v.z = w.z + separation(v._, w._);
29204         v.m = v.z - midpoint;
29205       } else {
29206         v.z = midpoint;
29207       }
29208     } else if (w) {
29209       v.z = w.z + separation(v._, w._);
29210     }
29211     v.parent.A = apportion(v, w, v.parent.A || siblings[0]);
29212   }
29213
29214   // Computes all real x-coordinates by summing up the modifiers recursively.
29215   function secondWalk(v) {
29216     v._.x = v.z + v.parent.m;
29217     v.m += v.parent.m;
29218   }
29219
29220   // The core of the algorithm. Here, a new subtree is combined with the
29221   // previous subtrees. Threads are used to traverse the inside and outside
29222   // contours of the left and right subtree up to the highest common level. The
29223   // vertices used for the traversals are vi+, vi-, vo-, and vo+, where the
29224   // superscript o means outside and i means inside, the subscript - means left
29225   // subtree and + means right subtree. For summing up the modifiers along the
29226   // contour, we use respective variables si+, si-, so-, and so+. Whenever two
29227   // nodes of the inside contours conflict, we compute the left one of the
29228   // greatest uncommon ancestors using the function ANCESTOR and call MOVE
29229   // SUBTREE to shift the subtree and prepare the shifts of smaller subtrees.
29230   // Finally, we add a new thread (if necessary).
29231   function apportion(v, w, ancestor) {
29232     if (w) {
29233       var vip = v,
29234           vop = v,
29235           vim = w,
29236           vom = vip.parent.children[0],
29237           sip = vip.m,
29238           sop = vop.m,
29239           sim = vim.m,
29240           som = vom.m,
29241           shift;
29242       while (vim = nextRight(vim), vip = nextLeft(vip), vim && vip) {
29243         vom = nextLeft(vom);
29244         vop = nextRight(vop);
29245         vop.a = v;
29246         shift = vim.z + sim - vip.z - sip + separation(vim._, vip._);
29247         if (shift > 0) {
29248           moveSubtree(nextAncestor(vim, v, ancestor), v, shift);
29249           sip += shift;
29250           sop += shift;
29251         }
29252         sim += vim.m;
29253         sip += vip.m;
29254         som += vom.m;
29255         sop += vop.m;
29256       }
29257       if (vim && !nextRight(vop)) {
29258         vop.t = vim;
29259         vop.m += sim - sop;
29260       }
29261       if (vip && !nextLeft(vom)) {
29262         vom.t = vip;
29263         vom.m += sip - som;
29264         ancestor = v;
29265       }
29266     }
29267     return ancestor;
29268   }
29269
29270   function sizeNode(node) {
29271     node.x *= dx;
29272     node.y = node.depth * dy;
29273   }
29274
29275   tree.separation = function(x) {
29276     return arguments.length ? (separation = x, tree) : separation;
29277   };
29278
29279   tree.size = function(x) {
29280     return arguments.length ? (nodeSize = false, dx = +x[0], dy = +x[1], tree) : (nodeSize ? null : [dx, dy]);
29281   };
29282
29283   tree.nodeSize = function(x) {
29284     return arguments.length ? (nodeSize = true, dx = +x[0], dy = +x[1], tree) : (nodeSize ? [dx, dy] : null);
29285   };
29286
29287   return tree;
29288 };
29289
29290 var treemapSlice = function(parent, x0, y0, x1, y1) {
29291   var nodes = parent.children,
29292       node,
29293       i = -1,
29294       n = nodes.length,
29295       k = parent.value && (y1 - y0) / parent.value;
29296
29297   while (++i < n) {
29298     node = nodes[i], node.x0 = x0, node.x1 = x1;
29299     node.y0 = y0, node.y1 = y0 += node.value * k;
29300   }
29301 };
29302
29303 var phi = (1 + Math.sqrt(5)) / 2;
29304
29305 function squarifyRatio(ratio, parent, x0, y0, x1, y1) {
29306   var rows = [],
29307       nodes = parent.children,
29308       row,
29309       nodeValue,
29310       i0 = 0,
29311       i1,
29312       n = nodes.length,
29313       dx, dy,
29314       value = parent.value,
29315       sumValue,
29316       minValue,
29317       maxValue,
29318       newRatio,
29319       minRatio,
29320       alpha,
29321       beta;
29322
29323   while (i0 < n) {
29324     dx = x1 - x0, dy = y1 - y0;
29325     minValue = maxValue = sumValue = nodes[i0].value;
29326     alpha = Math.max(dy / dx, dx / dy) / (value * ratio);
29327     beta = sumValue * sumValue * alpha;
29328     minRatio = Math.max(maxValue / beta, beta / minValue);
29329
29330     // Keep adding nodes while the aspect ratio maintains or improves.
29331     for (i1 = i0 + 1; i1 < n; ++i1) {
29332       sumValue += nodeValue = nodes[i1].value;
29333       if (nodeValue < minValue) minValue = nodeValue;
29334       if (nodeValue > maxValue) maxValue = nodeValue;
29335       beta = sumValue * sumValue * alpha;
29336       newRatio = Math.max(maxValue / beta, beta / minValue);
29337       if (newRatio > minRatio) { sumValue -= nodeValue; break; }
29338       minRatio = newRatio;
29339     }
29340
29341     // Position and record the row orientation.
29342     rows.push(row = {value: sumValue, dice: dx < dy, children: nodes.slice(i0, i1)});
29343     if (row.dice) treemapDice(row, x0, y0, x1, value ? y0 += dy * sumValue / value : y1);
29344     else treemapSlice(row, x0, y0, value ? x0 += dx * sumValue / value : x1, y1);
29345     value -= sumValue, i0 = i1;
29346   }
29347
29348   return rows;
29349 }
29350
29351 var squarify = (function custom(ratio) {
29352
29353   function squarify(parent, x0, y0, x1, y1) {
29354     squarifyRatio(ratio, parent, x0, y0, x1, y1);
29355   }
29356
29357   squarify.ratio = function(x) {
29358     return custom((x = +x) > 1 ? x : 1);
29359   };
29360
29361   return squarify;
29362 })(phi);
29363
29364 var index$3 = function() {
29365   var tile = squarify,
29366       round = false,
29367       dx = 1,
29368       dy = 1,
29369       paddingStack = [0],
29370       paddingInner = constantZero,
29371       paddingTop = constantZero,
29372       paddingRight = constantZero,
29373       paddingBottom = constantZero,
29374       paddingLeft = constantZero;
29375
29376   function treemap(root) {
29377     root.x0 =
29378     root.y0 = 0;
29379     root.x1 = dx;
29380     root.y1 = dy;
29381     root.eachBefore(positionNode);
29382     paddingStack = [0];
29383     if (round) root.eachBefore(roundNode);
29384     return root;
29385   }
29386
29387   function positionNode(node) {
29388     var p = paddingStack[node.depth],
29389         x0 = node.x0 + p,
29390         y0 = node.y0 + p,
29391         x1 = node.x1 - p,
29392         y1 = node.y1 - p;
29393     if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
29394     if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
29395     node.x0 = x0;
29396     node.y0 = y0;
29397     node.x1 = x1;
29398     node.y1 = y1;
29399     if (node.children) {
29400       p = paddingStack[node.depth + 1] = paddingInner(node) / 2;
29401       x0 += paddingLeft(node) - p;
29402       y0 += paddingTop(node) - p;
29403       x1 -= paddingRight(node) - p;
29404       y1 -= paddingBottom(node) - p;
29405       if (x1 < x0) x0 = x1 = (x0 + x1) / 2;
29406       if (y1 < y0) y0 = y1 = (y0 + y1) / 2;
29407       tile(node, x0, y0, x1, y1);
29408     }
29409   }
29410
29411   treemap.round = function(x) {
29412     return arguments.length ? (round = !!x, treemap) : round;
29413   };
29414
29415   treemap.size = function(x) {
29416     return arguments.length ? (dx = +x[0], dy = +x[1], treemap) : [dx, dy];
29417   };
29418
29419   treemap.tile = function(x) {
29420     return arguments.length ? (tile = required(x), treemap) : tile;
29421   };
29422
29423   treemap.padding = function(x) {
29424     return arguments.length ? treemap.paddingInner(x).paddingOuter(x) : treemap.paddingInner();
29425   };
29426
29427   treemap.paddingInner = function(x) {
29428     return arguments.length ? (paddingInner = typeof x === "function" ? x : constant$6(+x), treemap) : paddingInner;
29429   };
29430
29431   treemap.paddingOuter = function(x) {
29432     return arguments.length ? treemap.paddingTop(x).paddingRight(x).paddingBottom(x).paddingLeft(x) : treemap.paddingTop();
29433   };
29434
29435   treemap.paddingTop = function(x) {
29436     return arguments.length ? (paddingTop = typeof x === "function" ? x : constant$6(+x), treemap) : paddingTop;
29437   };
29438
29439   treemap.paddingRight = function(x) {
29440     return arguments.length ? (paddingRight = typeof x === "function" ? x : constant$6(+x), treemap) : paddingRight;
29441   };
29442
29443   treemap.paddingBottom = function(x) {
29444     return arguments.length ? (paddingBottom = typeof x === "function" ? x : constant$6(+x), treemap) : paddingBottom;
29445   };
29446
29447   treemap.paddingLeft = function(x) {
29448     return arguments.length ? (paddingLeft = typeof x === "function" ? x : constant$6(+x), treemap) : paddingLeft;
29449   };
29450
29451   return treemap;
29452 };
29453
29454 var binary = function(parent, x0, y0, x1, y1) {
29455   var nodes = parent.children,
29456       i, n = nodes.length,
29457       sum, sums = new Array(n + 1);
29458
29459   for (sums[0] = sum = i = 0; i < n; ++i) {
29460     sums[i + 1] = sum += nodes[i].value;
29461   }
29462
29463   partition(0, n, parent.value, x0, y0, x1, y1);
29464
29465   function partition(i, j, value, x0, y0, x1, y1) {
29466     if (i >= j - 1) {
29467       var node = nodes[i];
29468       node.x0 = x0, node.y0 = y0;
29469       node.x1 = x1, node.y1 = y1;
29470       return;
29471     }
29472
29473     var valueOffset = sums[i],
29474         valueTarget = (value / 2) + valueOffset,
29475         k = i + 1,
29476         hi = j - 1;
29477
29478     while (k < hi) {
29479       var mid = k + hi >>> 1;
29480       if (sums[mid] < valueTarget) k = mid + 1;
29481       else hi = mid;
29482     }
29483
29484     var valueLeft = sums[k] - valueOffset,
29485         valueRight = value - valueLeft;
29486
29487     if ((y1 - y0) > (x1 - x0)) {
29488       var yk = (y0 * valueRight + y1 * valueLeft) / value;
29489       partition(i, k, valueLeft, x0, y0, x1, yk);
29490       partition(k, j, valueRight, x0, yk, x1, y1);
29491     } else {
29492       var xk = (x0 * valueRight + x1 * valueLeft) / value;
29493       partition(i, k, valueLeft, x0, y0, xk, y1);
29494       partition(k, j, valueRight, xk, y0, x1, y1);
29495     }
29496   }
29497 };
29498
29499 var sliceDice = function(parent, x0, y0, x1, y1) {
29500   (parent.depth & 1 ? treemapSlice : treemapDice)(parent, x0, y0, x1, y1);
29501 };
29502
29503 var resquarify = (function custom(ratio) {
29504
29505   function resquarify(parent, x0, y0, x1, y1) {
29506     if ((rows = parent._squarify) && (rows.ratio === ratio)) {
29507       var rows,
29508           row,
29509           nodes,
29510           i,
29511           j = -1,
29512           n,
29513           m = rows.length,
29514           value = parent.value;
29515
29516       while (++j < m) {
29517         row = rows[j], nodes = row.children;
29518         for (i = row.value = 0, n = nodes.length; i < n; ++i) row.value += nodes[i].value;
29519         if (row.dice) treemapDice(row, x0, y0, x1, y0 += (y1 - y0) * row.value / value);
29520         else treemapSlice(row, x0, y0, x0 += (x1 - x0) * row.value / value, y1);
29521         value -= row.value;
29522       }
29523     } else {
29524       parent._squarify = rows = squarifyRatio(ratio, parent, x0, y0, x1, y1);
29525       rows.ratio = ratio;
29526     }
29527   }
29528
29529   resquarify.ratio = function(x) {
29530     return custom((x = +x) > 1 ? x : 1);
29531   };
29532
29533   return resquarify;
29534 })(phi);
29535
29536 var center$1 = function(x, y) {
29537   var nodes;
29538
29539   if (x == null) x = 0;
29540   if (y == null) y = 0;
29541
29542   function force() {
29543     var i,
29544         n = nodes.length,
29545         node,
29546         sx = 0,
29547         sy = 0;
29548
29549     for (i = 0; i < n; ++i) {
29550       node = nodes[i], sx += node.x, sy += node.y;
29551     }
29552
29553     for (sx = sx / n - x, sy = sy / n - y, i = 0; i < n; ++i) {
29554       node = nodes[i], node.x -= sx, node.y -= sy;
29555     }
29556   }
29557
29558   force.initialize = function(_) {
29559     nodes = _;
29560   };
29561
29562   force.x = function(_) {
29563     return arguments.length ? (x = +_, force) : x;
29564   };
29565
29566   force.y = function(_) {
29567     return arguments.length ? (y = +_, force) : y;
29568   };
29569
29570   return force;
29571 };
29572
29573 var constant$7 = function(x) {
29574   return function() {
29575     return x;
29576   };
29577 };
29578
29579 var jiggle = function() {
29580   return (Math.random() - 0.5) * 1e-6;
29581 };
29582
29583 function x$1(d) {
29584   return d.x + d.vx;
29585 }
29586
29587 function y$1(d) {
29588   return d.y + d.vy;
29589 }
29590
29591 var collide = function(radius) {
29592   var nodes,
29593       radii,
29594       strength = 1,
29595       iterations = 1;
29596
29597   if (typeof radius !== "function") radius = constant$7(radius == null ? 1 : +radius);
29598
29599   function force() {
29600     var i, n = nodes.length,
29601         tree,
29602         node,
29603         xi,
29604         yi,
29605         ri,
29606         ri2;
29607
29608     for (var k = 0; k < iterations; ++k) {
29609       tree = quadtree(nodes, x$1, y$1).visitAfter(prepare);
29610       for (i = 0; i < n; ++i) {
29611         node = nodes[i];
29612         ri = radii[i], ri2 = ri * ri;
29613         xi = node.x + node.vx;
29614         yi = node.y + node.vy;
29615         tree.visit(apply);
29616       }
29617     }
29618
29619     function apply(quad, x0, y0, x1, y1) {
29620       var data = quad.data, rj = quad.r, r = ri + rj;
29621       if (data) {
29622         if (data.index > i) {
29623           var x = xi - data.x - data.vx,
29624               y = yi - data.y - data.vy,
29625               l = x * x + y * y;
29626           if (l < r * r) {
29627             if (x === 0) x = jiggle(), l += x * x;
29628             if (y === 0) y = jiggle(), l += y * y;
29629             l = (r - (l = Math.sqrt(l))) / l * strength;
29630             node.vx += (x *= l) * (r = (rj *= rj) / (ri2 + rj));
29631             node.vy += (y *= l) * r;
29632             data.vx -= x * (r = 1 - r);
29633             data.vy -= y * r;
29634           }
29635         }
29636         return;
29637       }
29638       return x0 > xi + r || x1 < xi - r || y0 > yi + r || y1 < yi - r;
29639     }
29640   }
29641
29642   function prepare(quad) {
29643     if (quad.data) return quad.r = radii[quad.data.index];
29644     for (var i = quad.r = 0; i < 4; ++i) {
29645       if (quad[i] && quad[i].r > quad.r) {
29646         quad.r = quad[i].r;
29647       }
29648     }
29649   }
29650
29651   function initialize() {
29652     if (!nodes) return;
29653     var i, n = nodes.length;
29654     radii = new Array(n);
29655     for (i = 0; i < n; ++i) radii[i] = +radius(nodes[i], i, nodes);
29656   }
29657
29658   force.initialize = function(_) {
29659     nodes = _;
29660     initialize();
29661   };
29662
29663   force.iterations = function(_) {
29664     return arguments.length ? (iterations = +_, force) : iterations;
29665   };
29666
29667   force.strength = function(_) {
29668     return arguments.length ? (strength = +_, force) : strength;
29669   };
29670
29671   force.radius = function(_) {
29672     return arguments.length ? (radius = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : radius;
29673   };
29674
29675   return force;
29676 };
29677
29678 function index$4(d, i) {
29679   return i;
29680 }
29681
29682 function find(nodeById, nodeId) {
29683   var node = nodeById.get(nodeId);
29684   if (!node) throw new Error("missing: " + nodeId);
29685   return node;
29686 }
29687
29688 var link = function(links) {
29689   var id = index$4,
29690       strength = defaultStrength,
29691       strengths,
29692       distance = constant$7(30),
29693       distances,
29694       nodes,
29695       count,
29696       bias,
29697       iterations = 1;
29698
29699   if (links == null) links = [];
29700
29701   function defaultStrength(link) {
29702     return 1 / Math.min(count[link.source.index], count[link.target.index]);
29703   }
29704
29705   function force(alpha) {
29706     for (var k = 0, n = links.length; k < iterations; ++k) {
29707       for (var i = 0, link, source, target, x, y, l, b; i < n; ++i) {
29708         link = links[i], source = link.source, target = link.target;
29709         x = target.x + target.vx - source.x - source.vx || jiggle();
29710         y = target.y + target.vy - source.y - source.vy || jiggle();
29711         l = Math.sqrt(x * x + y * y);
29712         l = (l - distances[i]) / l * alpha * strengths[i];
29713         x *= l, y *= l;
29714         target.vx -= x * (b = bias[i]);
29715         target.vy -= y * b;
29716         source.vx += x * (b = 1 - b);
29717         source.vy += y * b;
29718       }
29719     }
29720   }
29721
29722   function initialize() {
29723     if (!nodes) return;
29724
29725     var i,
29726         n = nodes.length,
29727         m = links.length,
29728         nodeById = map$1(nodes, id),
29729         link;
29730
29731     for (i = 0, count = new Array(n); i < n; ++i) {
29732       count[i] = 0;
29733     }
29734
29735     for (i = 0; i < m; ++i) {
29736       link = links[i], link.index = i;
29737       if (typeof link.source !== "object") link.source = find(nodeById, link.source);
29738       if (typeof link.target !== "object") link.target = find(nodeById, link.target);
29739       ++count[link.source.index], ++count[link.target.index];
29740     }
29741
29742     for (i = 0, bias = new Array(m); i < m; ++i) {
29743       link = links[i], bias[i] = count[link.source.index] / (count[link.source.index] + count[link.target.index]);
29744     }
29745
29746     strengths = new Array(m), initializeStrength();
29747     distances = new Array(m), initializeDistance();
29748   }
29749
29750   function initializeStrength() {
29751     if (!nodes) return;
29752
29753     for (var i = 0, n = links.length; i < n; ++i) {
29754       strengths[i] = +strength(links[i], i, links);
29755     }
29756   }
29757
29758   function initializeDistance() {
29759     if (!nodes) return;
29760
29761     for (var i = 0, n = links.length; i < n; ++i) {
29762       distances[i] = +distance(links[i], i, links);
29763     }
29764   }
29765
29766   force.initialize = function(_) {
29767     nodes = _;
29768     initialize();
29769   };
29770
29771   force.links = function(_) {
29772     return arguments.length ? (links = _, initialize(), force) : links;
29773   };
29774
29775   force.id = function(_) {
29776     return arguments.length ? (id = _, force) : id;
29777   };
29778
29779   force.iterations = function(_) {
29780     return arguments.length ? (iterations = +_, force) : iterations;
29781   };
29782
29783   force.strength = function(_) {
29784     return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initializeStrength(), force) : strength;
29785   };
29786
29787   force.distance = function(_) {
29788     return arguments.length ? (distance = typeof _ === "function" ? _ : constant$7(+_), initializeDistance(), force) : distance;
29789   };
29790
29791   return force;
29792 };
29793
29794 function x$2(d) {
29795   return d.x;
29796 }
29797
29798 function y$2(d) {
29799   return d.y;
29800 }
29801
29802 var initialRadius = 10;
29803 var initialAngle = Math.PI * (3 - Math.sqrt(5));
29804
29805 var simulation = function(nodes) {
29806   var simulation,
29807       alpha = 1,
29808       alphaMin = 0.001,
29809       alphaDecay = 1 - Math.pow(alphaMin, 1 / 300),
29810       alphaTarget = 0,
29811       velocityDecay = 0.6,
29812       forces = map$1(),
29813       stepper = timer(step),
29814       event = dispatch("tick", "end");
29815
29816   if (nodes == null) nodes = [];
29817
29818   function step() {
29819     tick();
29820     event.call("tick", simulation);
29821     if (alpha < alphaMin) {
29822       stepper.stop();
29823       event.call("end", simulation);
29824     }
29825   }
29826
29827   function tick() {
29828     var i, n = nodes.length, node;
29829
29830     alpha += (alphaTarget - alpha) * alphaDecay;
29831
29832     forces.each(function(force) {
29833       force(alpha);
29834     });
29835
29836     for (i = 0; i < n; ++i) {
29837       node = nodes[i];
29838       if (node.fx == null) node.x += node.vx *= velocityDecay;
29839       else node.x = node.fx, node.vx = 0;
29840       if (node.fy == null) node.y += node.vy *= velocityDecay;
29841       else node.y = node.fy, node.vy = 0;
29842     }
29843   }
29844
29845   function initializeNodes() {
29846     for (var i = 0, n = nodes.length, node; i < n; ++i) {
29847       node = nodes[i], node.index = i;
29848       if (isNaN(node.x) || isNaN(node.y)) {
29849         var radius = initialRadius * Math.sqrt(i), angle = i * initialAngle;
29850         node.x = radius * Math.cos(angle);
29851         node.y = radius * Math.sin(angle);
29852       }
29853       if (isNaN(node.vx) || isNaN(node.vy)) {
29854         node.vx = node.vy = 0;
29855       }
29856     }
29857   }
29858
29859   function initializeForce(force) {
29860     if (force.initialize) force.initialize(nodes);
29861     return force;
29862   }
29863
29864   initializeNodes();
29865
29866   return simulation = {
29867     tick: tick,
29868
29869     restart: function() {
29870       return stepper.restart(step), simulation;
29871     },
29872
29873     stop: function() {
29874       return stepper.stop(), simulation;
29875     },
29876
29877     nodes: function(_) {
29878       return arguments.length ? (nodes = _, initializeNodes(), forces.each(initializeForce), simulation) : nodes;
29879     },
29880
29881     alpha: function(_) {
29882       return arguments.length ? (alpha = +_, simulation) : alpha;
29883     },
29884
29885     alphaMin: function(_) {
29886       return arguments.length ? (alphaMin = +_, simulation) : alphaMin;
29887     },
29888
29889     alphaDecay: function(_) {
29890       return arguments.length ? (alphaDecay = +_, simulation) : +alphaDecay;
29891     },
29892
29893     alphaTarget: function(_) {
29894       return arguments.length ? (alphaTarget = +_, simulation) : alphaTarget;
29895     },
29896
29897     velocityDecay: function(_) {
29898       return arguments.length ? (velocityDecay = 1 - _, simulation) : 1 - velocityDecay;
29899     },
29900
29901     force: function(name, _) {
29902       return arguments.length > 1 ? ((_ == null ? forces.remove(name) : forces.set(name, initializeForce(_))), simulation) : forces.get(name);
29903     },
29904
29905     find: function(x, y, radius) {
29906       var i = 0,
29907           n = nodes.length,
29908           dx,
29909           dy,
29910           d2,
29911           node,
29912           closest;
29913
29914       if (radius == null) radius = Infinity;
29915       else radius *= radius;
29916
29917       for (i = 0; i < n; ++i) {
29918         node = nodes[i];
29919         dx = x - node.x;
29920         dy = y - node.y;
29921         d2 = dx * dx + dy * dy;
29922         if (d2 < radius) closest = node, radius = d2;
29923       }
29924
29925       return closest;
29926     },
29927
29928     on: function(name, _) {
29929       return arguments.length > 1 ? (event.on(name, _), simulation) : event.on(name);
29930     }
29931   };
29932 };
29933
29934 var manyBody = function() {
29935   var nodes,
29936       node,
29937       alpha,
29938       strength = constant$7(-30),
29939       strengths,
29940       distanceMin2 = 1,
29941       distanceMax2 = Infinity,
29942       theta2 = 0.81;
29943
29944   function force(_) {
29945     var i, n = nodes.length, tree = quadtree(nodes, x$2, y$2).visitAfter(accumulate);
29946     for (alpha = _, i = 0; i < n; ++i) node = nodes[i], tree.visit(apply);
29947   }
29948
29949   function initialize() {
29950     if (!nodes) return;
29951     var i, n = nodes.length;
29952     strengths = new Array(n);
29953     for (i = 0; i < n; ++i) strengths[i] = +strength(nodes[i], i, nodes);
29954   }
29955
29956   function accumulate(quad) {
29957     var strength = 0, q, c, x$$1, y$$1, i;
29958
29959     // For internal nodes, accumulate forces from child quadrants.
29960     if (quad.length) {
29961       for (x$$1 = y$$1 = i = 0; i < 4; ++i) {
29962         if ((q = quad[i]) && (c = q.value)) {
29963           strength += c, x$$1 += c * q.x, y$$1 += c * q.y;
29964         }
29965       }
29966       quad.x = x$$1 / strength;
29967       quad.y = y$$1 / strength;
29968     }
29969
29970     // For leaf nodes, accumulate forces from coincident quadrants.
29971     else {
29972       q = quad;
29973       q.x = q.data.x;
29974       q.y = q.data.y;
29975       do strength += strengths[q.data.index];
29976       while (q = q.next);
29977     }
29978
29979     quad.value = strength;
29980   }
29981
29982   function apply(quad, x1, _, x2) {
29983     if (!quad.value) return true;
29984
29985     var x$$1 = quad.x - node.x,
29986         y$$1 = quad.y - node.y,
29987         w = x2 - x1,
29988         l = x$$1 * x$$1 + y$$1 * y$$1;
29989
29990     // Apply the Barnes-Hut approximation if possible.
29991     // Limit forces for very close nodes; randomize direction if coincident.
29992     if (w * w / theta2 < l) {
29993       if (l < distanceMax2) {
29994         if (x$$1 === 0) x$$1 = jiggle(), l += x$$1 * x$$1;
29995         if (y$$1 === 0) y$$1 = jiggle(), l += y$$1 * y$$1;
29996         if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);
29997         node.vx += x$$1 * quad.value * alpha / l;
29998         node.vy += y$$1 * quad.value * alpha / l;
29999       }
30000       return true;
30001     }
30002
30003     // Otherwise, process points directly.
30004     else if (quad.length || l >= distanceMax2) return;
30005
30006     // Limit forces for very close nodes; randomize direction if coincident.
30007     if (quad.data !== node || quad.next) {
30008       if (x$$1 === 0) x$$1 = jiggle(), l += x$$1 * x$$1;
30009       if (y$$1 === 0) y$$1 = jiggle(), l += y$$1 * y$$1;
30010       if (l < distanceMin2) l = Math.sqrt(distanceMin2 * l);
30011     }
30012
30013     do if (quad.data !== node) {
30014       w = strengths[quad.data.index] * alpha / l;
30015       node.vx += x$$1 * w;
30016       node.vy += y$$1 * w;
30017     } while (quad = quad.next);
30018   }
30019
30020   force.initialize = function(_) {
30021     nodes = _;
30022     initialize();
30023   };
30024
30025   force.strength = function(_) {
30026     return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : strength;
30027   };
30028
30029   force.distanceMin = function(_) {
30030     return arguments.length ? (distanceMin2 = _ * _, force) : Math.sqrt(distanceMin2);
30031   };
30032
30033   force.distanceMax = function(_) {
30034     return arguments.length ? (distanceMax2 = _ * _, force) : Math.sqrt(distanceMax2);
30035   };
30036
30037   force.theta = function(_) {
30038     return arguments.length ? (theta2 = _ * _, force) : Math.sqrt(theta2);
30039   };
30040
30041   return force;
30042 };
30043
30044 var x$3 = function(x) {
30045   var strength = constant$7(0.1),
30046       nodes,
30047       strengths,
30048       xz;
30049
30050   if (typeof x !== "function") x = constant$7(x == null ? 0 : +x);
30051
30052   function force(alpha) {
30053     for (var i = 0, n = nodes.length, node; i < n; ++i) {
30054       node = nodes[i], node.vx += (xz[i] - node.x) * strengths[i] * alpha;
30055     }
30056   }
30057
30058   function initialize() {
30059     if (!nodes) return;
30060     var i, n = nodes.length;
30061     strengths = new Array(n);
30062     xz = new Array(n);
30063     for (i = 0; i < n; ++i) {
30064       strengths[i] = isNaN(xz[i] = +x(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);
30065     }
30066   }
30067
30068   force.initialize = function(_) {
30069     nodes = _;
30070     initialize();
30071   };
30072
30073   force.strength = function(_) {
30074     return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : strength;
30075   };
30076
30077   force.x = function(_) {
30078     return arguments.length ? (x = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : x;
30079   };
30080
30081   return force;
30082 };
30083
30084 var y$3 = function(y) {
30085   var strength = constant$7(0.1),
30086       nodes,
30087       strengths,
30088       yz;
30089
30090   if (typeof y !== "function") y = constant$7(y == null ? 0 : +y);
30091
30092   function force(alpha) {
30093     for (var i = 0, n = nodes.length, node; i < n; ++i) {
30094       node = nodes[i], node.vy += (yz[i] - node.y) * strengths[i] * alpha;
30095     }
30096   }
30097
30098   function initialize() {
30099     if (!nodes) return;
30100     var i, n = nodes.length;
30101     strengths = new Array(n);
30102     yz = new Array(n);
30103     for (i = 0; i < n; ++i) {
30104       strengths[i] = isNaN(yz[i] = +y(nodes[i], i, nodes)) ? 0 : +strength(nodes[i], i, nodes);
30105     }
30106   }
30107
30108   force.initialize = function(_) {
30109     nodes = _;
30110     initialize();
30111   };
30112
30113   force.strength = function(_) {
30114     return arguments.length ? (strength = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : strength;
30115   };
30116
30117   force.y = function(_) {
30118     return arguments.length ? (y = typeof _ === "function" ? _ : constant$7(+_), initialize(), force) : y;
30119   };
30120
30121   return force;
30122 };
30123
30124 function nopropagation() {
30125   event.stopImmediatePropagation();
30126 }
30127
30128 var noevent = function() {
30129   event.preventDefault();
30130   event.stopImmediatePropagation();
30131 };
30132
30133 var dragDisable = function(view) {
30134   var root = view.document.documentElement,
30135       selection$$1 = select(view).on("dragstart.drag", noevent, true);
30136   if ("onselectstart" in root) {
30137     selection$$1.on("selectstart.drag", noevent, true);
30138   } else {
30139     root.__noselect = root.style.MozUserSelect;
30140     root.style.MozUserSelect = "none";
30141   }
30142 };
30143
30144 function yesdrag(view, noclick) {
30145   var root = view.document.documentElement,
30146       selection$$1 = select(view).on("dragstart.drag", null);
30147   if (noclick) {
30148     selection$$1.on("click.drag", noevent, true);
30149     setTimeout(function() { selection$$1.on("click.drag", null); }, 0);
30150   }
30151   if ("onselectstart" in root) {
30152     selection$$1.on("selectstart.drag", null);
30153   } else {
30154     root.style.MozUserSelect = root.__noselect;
30155     delete root.__noselect;
30156   }
30157 }
30158
30159 var constant$8 = function(x) {
30160   return function() {
30161     return x;
30162   };
30163 };
30164
30165 function DragEvent(target, type, subject, id, active, x, y, dx, dy, dispatch) {
30166   this.target = target;
30167   this.type = type;
30168   this.subject = subject;
30169   this.identifier = id;
30170   this.active = active;
30171   this.x = x;
30172   this.y = y;
30173   this.dx = dx;
30174   this.dy = dy;
30175   this._ = dispatch;
30176 }
30177
30178 DragEvent.prototype.on = function() {
30179   var value = this._.on.apply(this._, arguments);
30180   return value === this._ ? this : value;
30181 };
30182
30183 // Ignore right-click, since that should open the context menu.
30184 function defaultFilter() {
30185   return !event.button;
30186 }
30187
30188 function defaultContainer() {
30189   return this.parentNode;
30190 }
30191
30192 function defaultSubject(d) {
30193   return d == null ? {x: event.x, y: event.y} : d;
30194 }
30195
30196 var drag = function() {
30197   var filter = defaultFilter,
30198       container = defaultContainer,
30199       subject = defaultSubject,
30200       gestures = {},
30201       listeners = dispatch("start", "drag", "end"),
30202       active = 0,
30203       mousemoving,
30204       touchending;
30205
30206   function drag(selection$$1) {
30207     selection$$1
30208         .on("mousedown.drag", mousedowned)
30209         .on("touchstart.drag", touchstarted)
30210         .on("touchmove.drag", touchmoved)
30211         .on("touchend.drag touchcancel.drag", touchended)
30212         .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)");
30213   }
30214
30215   function mousedowned() {
30216     if (touchending || !filter.apply(this, arguments)) return;
30217     var gesture = beforestart("mouse", container.apply(this, arguments), mouse, this, arguments);
30218     if (!gesture) return;
30219     select(event.view).on("mousemove.drag", mousemoved, true).on("mouseup.drag", mouseupped, true);
30220     dragDisable(event.view);
30221     nopropagation();
30222     mousemoving = false;
30223     gesture("start");
30224   }
30225
30226   function mousemoved() {
30227     noevent();
30228     mousemoving = true;
30229     gestures.mouse("drag");
30230   }
30231
30232   function mouseupped() {
30233     select(event.view).on("mousemove.drag mouseup.drag", null);
30234     yesdrag(event.view, mousemoving);
30235     noevent();
30236     gestures.mouse("end");
30237   }
30238
30239   function touchstarted() {
30240     if (!filter.apply(this, arguments)) return;
30241     var touches$$1 = event.changedTouches,
30242         c = container.apply(this, arguments),
30243         n = touches$$1.length, i, gesture;
30244
30245     for (i = 0; i < n; ++i) {
30246       if (gesture = beforestart(touches$$1[i].identifier, c, touch, this, arguments)) {
30247         nopropagation();
30248         gesture("start");
30249       }
30250     }
30251   }
30252
30253   function touchmoved() {
30254     var touches$$1 = event.changedTouches,
30255         n = touches$$1.length, i, gesture;
30256
30257     for (i = 0; i < n; ++i) {
30258       if (gesture = gestures[touches$$1[i].identifier]) {
30259         noevent();
30260         gesture("drag");
30261       }
30262     }
30263   }
30264
30265   function touchended() {
30266     var touches$$1 = event.changedTouches,
30267         n = touches$$1.length, i, gesture;
30268
30269     if (touchending) clearTimeout(touchending);
30270     touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed!
30271     for (i = 0; i < n; ++i) {
30272       if (gesture = gestures[touches$$1[i].identifier]) {
30273         nopropagation();
30274         gesture("end");
30275       }
30276     }
30277   }
30278
30279   function beforestart(id, container, point, that, args) {
30280     var p = point(container, id), s, dx, dy,
30281         sublisteners = listeners.copy();
30282
30283     if (!customEvent(new DragEvent(drag, "beforestart", s, id, active, p[0], p[1], 0, 0, sublisteners), function() {
30284       if ((event.subject = s = subject.apply(that, args)) == null) return false;
30285       dx = s.x - p[0] || 0;
30286       dy = s.y - p[1] || 0;
30287       return true;
30288     })) return;
30289
30290     return function gesture(type) {
30291       var p0 = p, n;
30292       switch (type) {
30293         case "start": gestures[id] = gesture, n = active++; break;
30294         case "end": delete gestures[id], --active; // nobreak
30295         case "drag": p = point(container, id), n = active; break;
30296       }
30297       customEvent(new DragEvent(drag, type, s, id, n, p[0] + dx, p[1] + dy, p[0] - p0[0], p[1] - p0[1], sublisteners), sublisteners.apply, sublisteners, [type, that, args]);
30298     };
30299   }
30300
30301   drag.filter = function(_) {
30302     return arguments.length ? (filter = typeof _ === "function" ? _ : constant$8(!!_), drag) : filter;
30303   };
30304
30305   drag.container = function(_) {
30306     return arguments.length ? (container = typeof _ === "function" ? _ : constant$8(_), drag) : container;
30307   };
30308
30309   drag.subject = function(_) {
30310     return arguments.length ? (subject = typeof _ === "function" ? _ : constant$8(_), drag) : subject;
30311   };
30312
30313   drag.on = function() {
30314     var value = listeners.on.apply(listeners, arguments);
30315     return value === listeners ? drag : value;
30316   };
30317
30318   return drag;
30319 };
30320
30321 var constant$9 = function(x) {
30322   return function() {
30323     return x;
30324   };
30325 };
30326
30327 function x$4(d) {
30328   return d[0];
30329 }
30330
30331 function y$4(d) {
30332   return d[1];
30333 }
30334
30335 function RedBlackTree() {
30336   this._ = null; // root node
30337 }
30338
30339 function RedBlackNode(node) {
30340   node.U = // parent node
30341   node.C = // color - true for red, false for black
30342   node.L = // left node
30343   node.R = // right node
30344   node.P = // previous node
30345   node.N = null; // next node
30346 }
30347
30348 RedBlackTree.prototype = {
30349   constructor: RedBlackTree,
30350
30351   insert: function(after, node) {
30352     var parent, grandpa, uncle;
30353
30354     if (after) {
30355       node.P = after;
30356       node.N = after.N;
30357       if (after.N) after.N.P = node;
30358       after.N = node;
30359       if (after.R) {
30360         after = after.R;
30361         while (after.L) after = after.L;
30362         after.L = node;
30363       } else {
30364         after.R = node;
30365       }
30366       parent = after;
30367     } else if (this._) {
30368       after = RedBlackFirst(this._);
30369       node.P = null;
30370       node.N = after;
30371       after.P = after.L = node;
30372       parent = after;
30373     } else {
30374       node.P = node.N = null;
30375       this._ = node;
30376       parent = null;
30377     }
30378     node.L = node.R = null;
30379     node.U = parent;
30380     node.C = true;
30381
30382     after = node;
30383     while (parent && parent.C) {
30384       grandpa = parent.U;
30385       if (parent === grandpa.L) {
30386         uncle = grandpa.R;
30387         if (uncle && uncle.C) {
30388           parent.C = uncle.C = false;
30389           grandpa.C = true;
30390           after = grandpa;
30391         } else {
30392           if (after === parent.R) {
30393             RedBlackRotateLeft(this, parent);
30394             after = parent;
30395             parent = after.U;
30396           }
30397           parent.C = false;
30398           grandpa.C = true;
30399           RedBlackRotateRight(this, grandpa);
30400         }
30401       } else {
30402         uncle = grandpa.L;
30403         if (uncle && uncle.C) {
30404           parent.C = uncle.C = false;
30405           grandpa.C = true;
30406           after = grandpa;
30407         } else {
30408           if (after === parent.L) {
30409             RedBlackRotateRight(this, parent);
30410             after = parent;
30411             parent = after.U;
30412           }
30413           parent.C = false;
30414           grandpa.C = true;
30415           RedBlackRotateLeft(this, grandpa);
30416         }
30417       }
30418       parent = after.U;
30419     }
30420     this._.C = false;
30421   },
30422
30423   remove: function(node) {
30424     if (node.N) node.N.P = node.P;
30425     if (node.P) node.P.N = node.N;
30426     node.N = node.P = null;
30427
30428     var parent = node.U,
30429         sibling,
30430         left = node.L,
30431         right = node.R,
30432         next,
30433         red;
30434
30435     if (!left) next = right;
30436     else if (!right) next = left;
30437     else next = RedBlackFirst(right);
30438
30439     if (parent) {
30440       if (parent.L === node) parent.L = next;
30441       else parent.R = next;
30442     } else {
30443       this._ = next;
30444     }
30445
30446     if (left && right) {
30447       red = next.C;
30448       next.C = node.C;
30449       next.L = left;
30450       left.U = next;
30451       if (next !== right) {
30452         parent = next.U;
30453         next.U = node.U;
30454         node = next.R;
30455         parent.L = node;
30456         next.R = right;
30457         right.U = next;
30458       } else {
30459         next.U = parent;
30460         parent = next;
30461         node = next.R;
30462       }
30463     } else {
30464       red = node.C;
30465       node = next;
30466     }
30467
30468     if (node) node.U = parent;
30469     if (red) return;
30470     if (node && node.C) { node.C = false; return; }
30471
30472     do {
30473       if (node === this._) break;
30474       if (node === parent.L) {
30475         sibling = parent.R;
30476         if (sibling.C) {
30477           sibling.C = false;
30478           parent.C = true;
30479           RedBlackRotateLeft(this, parent);
30480           sibling = parent.R;
30481         }
30482         if ((sibling.L && sibling.L.C)
30483             || (sibling.R && sibling.R.C)) {
30484           if (!sibling.R || !sibling.R.C) {
30485             sibling.L.C = false;
30486             sibling.C = true;
30487             RedBlackRotateRight(this, sibling);
30488             sibling = parent.R;
30489           }
30490           sibling.C = parent.C;
30491           parent.C = sibling.R.C = false;
30492           RedBlackRotateLeft(this, parent);
30493           node = this._;
30494           break;
30495         }
30496       } else {
30497         sibling = parent.L;
30498         if (sibling.C) {
30499           sibling.C = false;
30500           parent.C = true;
30501           RedBlackRotateRight(this, parent);
30502           sibling = parent.L;
30503         }
30504         if ((sibling.L && sibling.L.C)
30505           || (sibling.R && sibling.R.C)) {
30506           if (!sibling.L || !sibling.L.C) {
30507             sibling.R.C = false;
30508             sibling.C = true;
30509             RedBlackRotateLeft(this, sibling);
30510             sibling = parent.L;
30511           }
30512           sibling.C = parent.C;
30513           parent.C = sibling.L.C = false;
30514           RedBlackRotateRight(this, parent);
30515           node = this._;
30516           break;
30517         }
30518       }
30519       sibling.C = true;
30520       node = parent;
30521       parent = parent.U;
30522     } while (!node.C);
30523
30524     if (node) node.C = false;
30525   }
30526 };
30527
30528 function RedBlackRotateLeft(tree, node) {
30529   var p = node,
30530       q = node.R,
30531       parent = p.U;
30532
30533   if (parent) {
30534     if (parent.L === p) parent.L = q;
30535     else parent.R = q;
30536   } else {
30537     tree._ = q;
30538   }
30539
30540   q.U = parent;
30541   p.U = q;
30542   p.R = q.L;
30543   if (p.R) p.R.U = p;
30544   q.L = p;
30545 }
30546
30547 function RedBlackRotateRight(tree, node) {
30548   var p = node,
30549       q = node.L,
30550       parent = p.U;
30551
30552   if (parent) {
30553     if (parent.L === p) parent.L = q;
30554     else parent.R = q;
30555   } else {
30556     tree._ = q;
30557   }
30558
30559   q.U = parent;
30560   p.U = q;
30561   p.L = q.R;
30562   if (p.L) p.L.U = p;
30563   q.R = p;
30564 }
30565
30566 function RedBlackFirst(node) {
30567   while (node.L) node = node.L;
30568   return node;
30569 }
30570
30571 function createEdge(left, right, v0, v1) {
30572   var edge = [null, null],
30573       index = edges.push(edge) - 1;
30574   edge.left = left;
30575   edge.right = right;
30576   if (v0) setEdgeEnd(edge, left, right, v0);
30577   if (v1) setEdgeEnd(edge, right, left, v1);
30578   cells[left.index].halfedges.push(index);
30579   cells[right.index].halfedges.push(index);
30580   return edge;
30581 }
30582
30583 function createBorderEdge(left, v0, v1) {
30584   var edge = [v0, v1];
30585   edge.left = left;
30586   return edge;
30587 }
30588
30589 function setEdgeEnd(edge, left, right, vertex) {
30590   if (!edge[0] && !edge[1]) {
30591     edge[0] = vertex;
30592     edge.left = left;
30593     edge.right = right;
30594   } else if (edge.left === right) {
30595     edge[1] = vertex;
30596   } else {
30597     edge[0] = vertex;
30598   }
30599 }
30600
30601 // Liang–Barsky line clipping.
30602 function clipEdge(edge, x0, y0, x1, y1) {
30603   var a = edge[0],
30604       b = edge[1],
30605       ax = a[0],
30606       ay = a[1],
30607       bx = b[0],
30608       by = b[1],
30609       t0 = 0,
30610       t1 = 1,
30611       dx = bx - ax,
30612       dy = by - ay,
30613       r;
30614
30615   r = x0 - ax;
30616   if (!dx && r > 0) return;
30617   r /= dx;
30618   if (dx < 0) {
30619     if (r < t0) return;
30620     if (r < t1) t1 = r;
30621   } else if (dx > 0) {
30622     if (r > t1) return;
30623     if (r > t0) t0 = r;
30624   }
30625
30626   r = x1 - ax;
30627   if (!dx && r < 0) return;
30628   r /= dx;
30629   if (dx < 0) {
30630     if (r > t1) return;
30631     if (r > t0) t0 = r;
30632   } else if (dx > 0) {
30633     if (r < t0) return;
30634     if (r < t1) t1 = r;
30635   }
30636
30637   r = y0 - ay;
30638   if (!dy && r > 0) return;
30639   r /= dy;
30640   if (dy < 0) {
30641     if (r < t0) return;
30642     if (r < t1) t1 = r;
30643   } else if (dy > 0) {
30644     if (r > t1) return;
30645     if (r > t0) t0 = r;
30646   }
30647
30648   r = y1 - ay;
30649   if (!dy && r < 0) return;
30650   r /= dy;
30651   if (dy < 0) {
30652     if (r > t1) return;
30653     if (r > t0) t0 = r;
30654   } else if (dy > 0) {
30655     if (r < t0) return;
30656     if (r < t1) t1 = r;
30657   }
30658
30659   if (!(t0 > 0) && !(t1 < 1)) return true; // TODO Better check?
30660
30661   if (t0 > 0) edge[0] = [ax + t0 * dx, ay + t0 * dy];
30662   if (t1 < 1) edge[1] = [ax + t1 * dx, ay + t1 * dy];
30663   return true;
30664 }
30665
30666 function connectEdge(edge, x0, y0, x1, y1) {
30667   var v1 = edge[1];
30668   if (v1) return true;
30669
30670   var v0 = edge[0],
30671       left = edge.left,
30672       right = edge.right,
30673       lx = left[0],
30674       ly = left[1],
30675       rx = right[0],
30676       ry = right[1],
30677       fx = (lx + rx) / 2,
30678       fy = (ly + ry) / 2,
30679       fm,
30680       fb;
30681
30682   if (ry === ly) {
30683     if (fx < x0 || fx >= x1) return;
30684     if (lx > rx) {
30685       if (!v0) v0 = [fx, y0];
30686       else if (v0[1] >= y1) return;
30687       v1 = [fx, y1];
30688     } else {
30689       if (!v0) v0 = [fx, y1];
30690       else if (v0[1] < y0) return;
30691       v1 = [fx, y0];
30692     }
30693   } else {
30694     fm = (lx - rx) / (ry - ly);
30695     fb = fy - fm * fx;
30696     if (fm < -1 || fm > 1) {
30697       if (lx > rx) {
30698         if (!v0) v0 = [(y0 - fb) / fm, y0];
30699         else if (v0[1] >= y1) return;
30700         v1 = [(y1 - fb) / fm, y1];
30701       } else {
30702         if (!v0) v0 = [(y1 - fb) / fm, y1];
30703         else if (v0[1] < y0) return;
30704         v1 = [(y0 - fb) / fm, y0];
30705       }
30706     } else {
30707       if (ly < ry) {
30708         if (!v0) v0 = [x0, fm * x0 + fb];
30709         else if (v0[0] >= x1) return;
30710         v1 = [x1, fm * x1 + fb];
30711       } else {
30712         if (!v0) v0 = [x1, fm * x1 + fb];
30713         else if (v0[0] < x0) return;
30714         v1 = [x0, fm * x0 + fb];
30715       }
30716     }
30717   }
30718
30719   edge[0] = v0;
30720   edge[1] = v1;
30721   return true;
30722 }
30723
30724 function clipEdges(x0, y0, x1, y1) {
30725   var i = edges.length,
30726       edge;
30727
30728   while (i--) {
30729     if (!connectEdge(edge = edges[i], x0, y0, x1, y1)
30730         || !clipEdge(edge, x0, y0, x1, y1)
30731         || !(Math.abs(edge[0][0] - edge[1][0]) > epsilon$3
30732             || Math.abs(edge[0][1] - edge[1][1]) > epsilon$3)) {
30733       delete edges[i];
30734     }
30735   }
30736 }
30737
30738 function createCell(site) {
30739   return cells[site.index] = {
30740     site: site,
30741     halfedges: []
30742   };
30743 }
30744
30745 function cellHalfedgeAngle(cell, edge) {
30746   var site = cell.site,
30747       va = edge.left,
30748       vb = edge.right;
30749   if (site === vb) vb = va, va = site;
30750   if (vb) return Math.atan2(vb[1] - va[1], vb[0] - va[0]);
30751   if (site === va) va = edge[1], vb = edge[0];
30752   else va = edge[0], vb = edge[1];
30753   return Math.atan2(va[0] - vb[0], vb[1] - va[1]);
30754 }
30755
30756 function cellHalfedgeStart(cell, edge) {
30757   return edge[+(edge.left !== cell.site)];
30758 }
30759
30760 function cellHalfedgeEnd(cell, edge) {
30761   return edge[+(edge.left === cell.site)];
30762 }
30763
30764 function sortCellHalfedges() {
30765   for (var i = 0, n = cells.length, cell, halfedges, j, m; i < n; ++i) {
30766     if ((cell = cells[i]) && (m = (halfedges = cell.halfedges).length)) {
30767       var index = new Array(m),
30768           array = new Array(m);
30769       for (j = 0; j < m; ++j) index[j] = j, array[j] = cellHalfedgeAngle(cell, edges[halfedges[j]]);
30770       index.sort(function(i, j) { return array[j] - array[i]; });
30771       for (j = 0; j < m; ++j) array[j] = halfedges[index[j]];
30772       for (j = 0; j < m; ++j) halfedges[j] = array[j];
30773     }
30774   }
30775 }
30776
30777 function clipCells(x0, y0, x1, y1) {
30778   var nCells = cells.length,
30779       iCell,
30780       cell,
30781       site,
30782       iHalfedge,
30783       halfedges,
30784       nHalfedges,
30785       start,
30786       startX,
30787       startY,
30788       end,
30789       endX,
30790       endY,
30791       cover = true;
30792
30793   for (iCell = 0; iCell < nCells; ++iCell) {
30794     if (cell = cells[iCell]) {
30795       site = cell.site;
30796       halfedges = cell.halfedges;
30797       iHalfedge = halfedges.length;
30798
30799       // Remove any dangling clipped edges.
30800       while (iHalfedge--) {
30801         if (!edges[halfedges[iHalfedge]]) {
30802           halfedges.splice(iHalfedge, 1);
30803         }
30804       }
30805
30806       // Insert any border edges as necessary.
30807       iHalfedge = 0, nHalfedges = halfedges.length;
30808       while (iHalfedge < nHalfedges) {
30809         end = cellHalfedgeEnd(cell, edges[halfedges[iHalfedge]]), endX = end[0], endY = end[1];
30810         start = cellHalfedgeStart(cell, edges[halfedges[++iHalfedge % nHalfedges]]), startX = start[0], startY = start[1];
30811         if (Math.abs(endX - startX) > epsilon$3 || Math.abs(endY - startY) > epsilon$3) {
30812           halfedges.splice(iHalfedge, 0, edges.push(createBorderEdge(site, end,
30813               Math.abs(endX - x0) < epsilon$3 && y1 - endY > epsilon$3 ? [x0, Math.abs(startX - x0) < epsilon$3 ? startY : y1]
30814               : Math.abs(endY - y1) < epsilon$3 && x1 - endX > epsilon$3 ? [Math.abs(startY - y1) < epsilon$3 ? startX : x1, y1]
30815               : Math.abs(endX - x1) < epsilon$3 && endY - y0 > epsilon$3 ? [x1, Math.abs(startX - x1) < epsilon$3 ? startY : y0]
30816               : Math.abs(endY - y0) < epsilon$3 && endX - x0 > epsilon$3 ? [Math.abs(startY - y0) < epsilon$3 ? startX : x0, y0]
30817               : null)) - 1);
30818           ++nHalfedges;
30819         }
30820       }
30821
30822       if (nHalfedges) cover = false;
30823     }
30824   }
30825
30826   // If there weren’t any edges, have the closest site cover the extent.
30827   // It doesn’t matter which corner of the extent we measure!
30828   if (cover) {
30829     var dx, dy, d2, dc = Infinity;
30830
30831     for (iCell = 0, cover = null; iCell < nCells; ++iCell) {
30832       if (cell = cells[iCell]) {
30833         site = cell.site;
30834         dx = site[0] - x0;
30835         dy = site[1] - y0;
30836         d2 = dx * dx + dy * dy;
30837         if (d2 < dc) dc = d2, cover = cell;
30838       }
30839     }
30840
30841     if (cover) {
30842       var v00 = [x0, y0], v01 = [x0, y1], v11 = [x1, y1], v10 = [x1, y0];
30843       cover.halfedges.push(
30844         edges.push(createBorderEdge(site = cover.site, v00, v01)) - 1,
30845         edges.push(createBorderEdge(site, v01, v11)) - 1,
30846         edges.push(createBorderEdge(site, v11, v10)) - 1,
30847         edges.push(createBorderEdge(site, v10, v00)) - 1
30848       );
30849     }
30850   }
30851
30852   // Lastly delete any cells with no edges; these were entirely clipped.
30853   for (iCell = 0; iCell < nCells; ++iCell) {
30854     if (cell = cells[iCell]) {
30855       if (!cell.halfedges.length) {
30856         delete cells[iCell];
30857       }
30858     }
30859   }
30860 }
30861
30862 var circlePool = [];
30863
30864 var firstCircle;
30865
30866 function Circle() {
30867   RedBlackNode(this);
30868   this.x =
30869   this.y =
30870   this.arc =
30871   this.site =
30872   this.cy = null;
30873 }
30874
30875 function attachCircle(arc) {
30876   var lArc = arc.P,
30877       rArc = arc.N;
30878
30879   if (!lArc || !rArc) return;
30880
30881   var lSite = lArc.site,
30882       cSite = arc.site,
30883       rSite = rArc.site;
30884
30885   if (lSite === rSite) return;
30886
30887   var bx = cSite[0],
30888       by = cSite[1],
30889       ax = lSite[0] - bx,
30890       ay = lSite[1] - by,
30891       cx = rSite[0] - bx,
30892       cy = rSite[1] - by;
30893
30894   var d = 2 * (ax * cy - ay * cx);
30895   if (d >= -epsilon2$1) return;
30896
30897   var ha = ax * ax + ay * ay,
30898       hc = cx * cx + cy * cy,
30899       x = (cy * ha - ay * hc) / d,
30900       y = (ax * hc - cx * ha) / d;
30901
30902   var circle = circlePool.pop() || new Circle;
30903   circle.arc = arc;
30904   circle.site = cSite;
30905   circle.x = x + bx;
30906   circle.y = (circle.cy = y + by) + Math.sqrt(x * x + y * y); // y bottom
30907
30908   arc.circle = circle;
30909
30910   var before = null,
30911       node = circles._;
30912
30913   while (node) {
30914     if (circle.y < node.y || (circle.y === node.y && circle.x <= node.x)) {
30915       if (node.L) node = node.L;
30916       else { before = node.P; break; }
30917     } else {
30918       if (node.R) node = node.R;
30919       else { before = node; break; }
30920     }
30921   }
30922
30923   circles.insert(before, circle);
30924   if (!before) firstCircle = circle;
30925 }
30926
30927 function detachCircle(arc) {
30928   var circle = arc.circle;
30929   if (circle) {
30930     if (!circle.P) firstCircle = circle.N;
30931     circles.remove(circle);
30932     circlePool.push(circle);
30933     RedBlackNode(circle);
30934     arc.circle = null;
30935   }
30936 }
30937
30938 var beachPool = [];
30939
30940 function Beach() {
30941   RedBlackNode(this);
30942   this.edge =
30943   this.site =
30944   this.circle = null;
30945 }
30946
30947 function createBeach(site) {
30948   var beach = beachPool.pop() || new Beach;
30949   beach.site = site;
30950   return beach;
30951 }
30952
30953 function detachBeach(beach) {
30954   detachCircle(beach);
30955   beaches.remove(beach);
30956   beachPool.push(beach);
30957   RedBlackNode(beach);
30958 }
30959
30960 function removeBeach(beach) {
30961   var circle = beach.circle,
30962       x = circle.x,
30963       y = circle.cy,
30964       vertex = [x, y],
30965       previous = beach.P,
30966       next = beach.N,
30967       disappearing = [beach];
30968
30969   detachBeach(beach);
30970
30971   var lArc = previous;
30972   while (lArc.circle
30973       && Math.abs(x - lArc.circle.x) < epsilon$3
30974       && Math.abs(y - lArc.circle.cy) < epsilon$3) {
30975     previous = lArc.P;
30976     disappearing.unshift(lArc);
30977     detachBeach(lArc);
30978     lArc = previous;
30979   }
30980
30981   disappearing.unshift(lArc);
30982   detachCircle(lArc);
30983
30984   var rArc = next;
30985   while (rArc.circle
30986       && Math.abs(x - rArc.circle.x) < epsilon$3
30987       && Math.abs(y - rArc.circle.cy) < epsilon$3) {
30988     next = rArc.N;
30989     disappearing.push(rArc);
30990     detachBeach(rArc);
30991     rArc = next;
30992   }
30993
30994   disappearing.push(rArc);
30995   detachCircle(rArc);
30996
30997   var nArcs = disappearing.length,
30998       iArc;
30999   for (iArc = 1; iArc < nArcs; ++iArc) {
31000     rArc = disappearing[iArc];
31001     lArc = disappearing[iArc - 1];
31002     setEdgeEnd(rArc.edge, lArc.site, rArc.site, vertex);
31003   }
31004
31005   lArc = disappearing[0];
31006   rArc = disappearing[nArcs - 1];
31007   rArc.edge = createEdge(lArc.site, rArc.site, null, vertex);
31008
31009   attachCircle(lArc);
31010   attachCircle(rArc);
31011 }
31012
31013 function addBeach(site) {
31014   var x = site[0],
31015       directrix = site[1],
31016       lArc,
31017       rArc,
31018       dxl,
31019       dxr,
31020       node = beaches._;
31021
31022   while (node) {
31023     dxl = leftBreakPoint(node, directrix) - x;
31024     if (dxl > epsilon$3) node = node.L; else {
31025       dxr = x - rightBreakPoint(node, directrix);
31026       if (dxr > epsilon$3) {
31027         if (!node.R) {
31028           lArc = node;
31029           break;
31030         }
31031         node = node.R;
31032       } else {
31033         if (dxl > -epsilon$3) {
31034           lArc = node.P;
31035           rArc = node;
31036         } else if (dxr > -epsilon$3) {
31037           lArc = node;
31038           rArc = node.N;
31039         } else {
31040           lArc = rArc = node;
31041         }
31042         break;
31043       }
31044     }
31045   }
31046
31047   createCell(site);
31048   var newArc = createBeach(site);
31049   beaches.insert(lArc, newArc);
31050
31051   if (!lArc && !rArc) return;
31052
31053   if (lArc === rArc) {
31054     detachCircle(lArc);
31055     rArc = createBeach(lArc.site);
31056     beaches.insert(newArc, rArc);
31057     newArc.edge = rArc.edge = createEdge(lArc.site, newArc.site);
31058     attachCircle(lArc);
31059     attachCircle(rArc);
31060     return;
31061   }
31062
31063   if (!rArc) { // && lArc
31064     newArc.edge = createEdge(lArc.site, newArc.site);
31065     return;
31066   }
31067
31068   // else lArc !== rArc
31069   detachCircle(lArc);
31070   detachCircle(rArc);
31071
31072   var lSite = lArc.site,
31073       ax = lSite[0],
31074       ay = lSite[1],
31075       bx = site[0] - ax,
31076       by = site[1] - ay,
31077       rSite = rArc.site,
31078       cx = rSite[0] - ax,
31079       cy = rSite[1] - ay,
31080       d = 2 * (bx * cy - by * cx),
31081       hb = bx * bx + by * by,
31082       hc = cx * cx + cy * cy,
31083       vertex = [(cy * hb - by * hc) / d + ax, (bx * hc - cx * hb) / d + ay];
31084
31085   setEdgeEnd(rArc.edge, lSite, rSite, vertex);
31086   newArc.edge = createEdge(lSite, site, null, vertex);
31087   rArc.edge = createEdge(site, rSite, null, vertex);
31088   attachCircle(lArc);
31089   attachCircle(rArc);
31090 }
31091
31092 function leftBreakPoint(arc, directrix) {
31093   var site = arc.site,
31094       rfocx = site[0],
31095       rfocy = site[1],
31096       pby2 = rfocy - directrix;
31097
31098   if (!pby2) return rfocx;
31099
31100   var lArc = arc.P;
31101   if (!lArc) return -Infinity;
31102
31103   site = lArc.site;
31104   var lfocx = site[0],
31105       lfocy = site[1],
31106       plby2 = lfocy - directrix;
31107
31108   if (!plby2) return lfocx;
31109
31110   var hl = lfocx - rfocx,
31111       aby2 = 1 / pby2 - 1 / plby2,
31112       b = hl / plby2;
31113
31114   if (aby2) return (-b + Math.sqrt(b * b - 2 * aby2 * (hl * hl / (-2 * plby2) - lfocy + plby2 / 2 + rfocy - pby2 / 2))) / aby2 + rfocx;
31115
31116   return (rfocx + lfocx) / 2;
31117 }
31118
31119 function rightBreakPoint(arc, directrix) {
31120   var rArc = arc.N;
31121   if (rArc) return leftBreakPoint(rArc, directrix);
31122   var site = arc.site;
31123   return site[1] === directrix ? site[0] : Infinity;
31124 }
31125
31126 var epsilon$3 = 1e-6;
31127 var epsilon2$1 = 1e-12;
31128 var beaches;
31129 var cells;
31130 var circles;
31131 var edges;
31132
31133 function triangleArea(a, b, c) {
31134   return (a[0] - c[0]) * (b[1] - a[1]) - (a[0] - b[0]) * (c[1] - a[1]);
31135 }
31136
31137 function lexicographic(a, b) {
31138   return b[1] - a[1]
31139       || b[0] - a[0];
31140 }
31141
31142 function Diagram(sites, extent) {
31143   var site = sites.sort(lexicographic).pop(),
31144       x,
31145       y,
31146       circle;
31147
31148   edges = [];
31149   cells = new Array(sites.length);
31150   beaches = new RedBlackTree;
31151   circles = new RedBlackTree;
31152
31153   while (true) {
31154     circle = firstCircle;
31155     if (site && (!circle || site[1] < circle.y || (site[1] === circle.y && site[0] < circle.x))) {
31156       if (site[0] !== x || site[1] !== y) {
31157         addBeach(site);
31158         x = site[0], y = site[1];
31159       }
31160       site = sites.pop();
31161     } else if (circle) {
31162       removeBeach(circle.arc);
31163     } else {
31164       break;
31165     }
31166   }
31167
31168   sortCellHalfedges();
31169
31170   if (extent) {
31171     var x0 = +extent[0][0],
31172         y0 = +extent[0][1],
31173         x1 = +extent[1][0],
31174         y1 = +extent[1][1];
31175     clipEdges(x0, y0, x1, y1);
31176     clipCells(x0, y0, x1, y1);
31177   }
31178
31179   this.edges = edges;
31180   this.cells = cells;
31181
31182   beaches =
31183   circles =
31184   edges =
31185   cells = null;
31186 }
31187
31188 Diagram.prototype = {
31189   constructor: Diagram,
31190
31191   polygons: function() {
31192     var edges = this.edges;
31193
31194     return this.cells.map(function(cell) {
31195       var polygon = cell.halfedges.map(function(i) { return cellHalfedgeStart(cell, edges[i]); });
31196       polygon.data = cell.site.data;
31197       return polygon;
31198     });
31199   },
31200
31201   triangles: function() {
31202     var triangles = [],
31203         edges = this.edges;
31204
31205     this.cells.forEach(function(cell, i) {
31206       var site = cell.site,
31207           halfedges = cell.halfedges,
31208           j = -1,
31209           m = halfedges.length,
31210           s0,
31211           e1 = edges[halfedges[m - 1]],
31212           s1 = e1.left === site ? e1.right : e1.left;
31213
31214       while (++j < m) {
31215         s0 = s1;
31216         e1 = edges[halfedges[j]];
31217         s1 = e1.left === site ? e1.right : e1.left;
31218         if (s0 && s1 && i < s0.index && i < s1.index && triangleArea(site, s0, s1) < 0) {
31219           triangles.push([site.data, s0.data, s1.data]);
31220         }
31221       }
31222     });
31223
31224     return triangles;
31225   },
31226
31227   links: function() {
31228     return this.edges.filter(function(edge) {
31229       return edge.right;
31230     }).map(function(edge) {
31231       return {
31232         source: edge.left.data,
31233         target: edge.right.data
31234       };
31235     });
31236   },
31237
31238   find: function(x, y, radius) {
31239     var that = this,
31240         i0, i1 = that._found || 0,
31241         cell = that.cells[i1] || that.cells[i1 = 0],
31242         dx = x - cell.site[0],
31243         dy = y - cell.site[1],
31244         d2 = dx * dx + dy * dy;
31245
31246     do {
31247       cell = that.cells[i0 = i1], i1 = null;
31248       cell.halfedges.forEach(function(e) {
31249         var edge = that.edges[e], v = edge.left;
31250         if ((v === cell.site || !v) && !(v = edge.right)) return;
31251         var vx = x - v[0],
31252             vy = y - v[1],
31253             v2 = vx * vx + vy * vy;
31254         if (v2 < d2) d2 = v2, i1 = v.index;
31255       });
31256     } while (i1 !== null);
31257
31258     that._found = i0;
31259
31260     return radius == null || d2 <= radius * radius ? cell.site : null;
31261   }
31262 };
31263
31264 var voronoi = function() {
31265   var x$$1 = x$4,
31266       y$$1 = y$4,
31267       extent = null;
31268
31269   function voronoi(data) {
31270     return new Diagram(data.map(function(d, i) {
31271       var s = [Math.round(x$$1(d, i, data) / epsilon$3) * epsilon$3, Math.round(y$$1(d, i, data) / epsilon$3) * epsilon$3];
31272       s.index = i;
31273       s.data = d;
31274       return s;
31275     }), extent);
31276   }
31277
31278   voronoi.polygons = function(data) {
31279     return voronoi(data).polygons();
31280   };
31281
31282   voronoi.links = function(data) {
31283     return voronoi(data).links();
31284   };
31285
31286   voronoi.triangles = function(data) {
31287     return voronoi(data).triangles();
31288   };
31289
31290   voronoi.x = function(_) {
31291     return arguments.length ? (x$$1 = typeof _ === "function" ? _ : constant$9(+_), voronoi) : x$$1;
31292   };
31293
31294   voronoi.y = function(_) {
31295     return arguments.length ? (y$$1 = typeof _ === "function" ? _ : constant$9(+_), voronoi) : y$$1;
31296   };
31297
31298   voronoi.extent = function(_) {
31299     return arguments.length ? (extent = _ == null ? null : [[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]], voronoi) : extent && [[extent[0][0], extent[0][1]], [extent[1][0], extent[1][1]]];
31300   };
31301
31302   voronoi.size = function(_) {
31303     return arguments.length ? (extent = _ == null ? null : [[0, 0], [+_[0], +_[1]]], voronoi) : extent && [extent[1][0] - extent[0][0], extent[1][1] - extent[0][1]];
31304   };
31305
31306   return voronoi;
31307 };
31308
31309 var constant$10 = function(x) {
31310   return function() {
31311     return x;
31312   };
31313 };
31314
31315 function ZoomEvent(target, type, transform) {
31316   this.target = target;
31317   this.type = type;
31318   this.transform = transform;
31319 }
31320
31321 function Transform(k, x, y) {
31322   this.k = k;
31323   this.x = x;
31324   this.y = y;
31325 }
31326
31327 Transform.prototype = {
31328   constructor: Transform,
31329   scale: function(k) {
31330     return k === 1 ? this : new Transform(this.k * k, this.x, this.y);
31331   },
31332   translate: function(x, y) {
31333     return x === 0 & y === 0 ? this : new Transform(this.k, this.x + this.k * x, this.y + this.k * y);
31334   },
31335   apply: function(point) {
31336     return [point[0] * this.k + this.x, point[1] * this.k + this.y];
31337   },
31338   applyX: function(x) {
31339     return x * this.k + this.x;
31340   },
31341   applyY: function(y) {
31342     return y * this.k + this.y;
31343   },
31344   invert: function(location) {
31345     return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k];
31346   },
31347   invertX: function(x) {
31348     return (x - this.x) / this.k;
31349   },
31350   invertY: function(y) {
31351     return (y - this.y) / this.k;
31352   },
31353   rescaleX: function(x) {
31354     return x.copy().domain(x.range().map(this.invertX, this).map(x.invert, x));
31355   },
31356   rescaleY: function(y) {
31357     return y.copy().domain(y.range().map(this.invertY, this).map(y.invert, y));
31358   },
31359   toString: function() {
31360     return "translate(" + this.x + "," + this.y + ") scale(" + this.k + ")";
31361   }
31362 };
31363
31364 var identity$6 = new Transform(1, 0, 0);
31365
31366 transform.prototype = Transform.prototype;
31367
31368 function transform(node) {
31369   return node.__zoom || identity$6;
31370 }
31371
31372 function nopropagation$1() {
31373   event.stopImmediatePropagation();
31374 }
31375
31376 var noevent$1 = function() {
31377   event.preventDefault();
31378   event.stopImmediatePropagation();
31379 };
31380
31381 // Ignore right-click, since that should open the context menu.
31382 function defaultFilter$1() {
31383   return !event.button;
31384 }
31385
31386 function defaultExtent() {
31387   var e = this, w, h;
31388   if (e instanceof SVGElement) {
31389     e = e.ownerSVGElement || e;
31390     w = e.width.baseVal.value;
31391     h = e.height.baseVal.value;
31392   } else {
31393     w = e.clientWidth;
31394     h = e.clientHeight;
31395   }
31396   return [[0, 0], [w, h]];
31397 }
31398
31399 function defaultTransform() {
31400   return this.__zoom || identity$6;
31401 }
31402
31403 var zoom = function() {
31404   var filter = defaultFilter$1,
31405       extent = defaultExtent,
31406       k0 = 0,
31407       k1 = Infinity,
31408       x0 = -k1,
31409       x1 = k1,
31410       y0 = x0,
31411       y1 = x1,
31412       duration = 250,
31413       gestures = [],
31414       listeners = dispatch("start", "zoom", "end"),
31415       touchstarting,
31416       touchending,
31417       touchDelay = 500,
31418       wheelDelay = 150;
31419
31420   function zoom(selection$$1) {
31421     selection$$1
31422         .on("wheel.zoom", wheeled)
31423         .on("mousedown.zoom", mousedowned)
31424         .on("dblclick.zoom", dblclicked)
31425         .on("touchstart.zoom", touchstarted)
31426         .on("touchmove.zoom", touchmoved)
31427         .on("touchend.zoom touchcancel.zoom", touchended)
31428         .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)")
31429         .property("__zoom", defaultTransform);
31430   }
31431
31432   zoom.transform = function(collection, transform) {
31433     var selection$$1 = collection.selection ? collection.selection() : collection;
31434     selection$$1.property("__zoom", defaultTransform);
31435     if (collection !== selection$$1) {
31436       schedule(collection, transform);
31437     } else {
31438       selection$$1.interrupt().each(function() {
31439         gesture(this, arguments)
31440             .start()
31441             .zoom(null, typeof transform === "function" ? transform.apply(this, arguments) : transform)
31442             .end();
31443       });
31444     }
31445   };
31446
31447   zoom.scaleBy = function(selection$$1, k) {
31448     zoom.scaleTo(selection$$1, function() {
31449       var k0 = this.__zoom.k,
31450           k1 = typeof k === "function" ? k.apply(this, arguments) : k;
31451       return k0 * k1;
31452     });
31453   };
31454
31455   zoom.scaleTo = function(selection$$1, k) {
31456     zoom.transform(selection$$1, function() {
31457       var e = extent.apply(this, arguments),
31458           t0 = this.__zoom,
31459           p0 = centroid(e),
31460           p1 = t0.invert(p0),
31461           k1 = typeof k === "function" ? k.apply(this, arguments) : k;
31462       return constrain(translate(scale(t0, k1), p0, p1), e);
31463     });
31464   };
31465
31466   zoom.translateBy = function(selection$$1, x, y) {
31467     zoom.transform(selection$$1, function() {
31468       return constrain(this.__zoom.translate(
31469         typeof x === "function" ? x.apply(this, arguments) : x,
31470         typeof y === "function" ? y.apply(this, arguments) : y
31471       ), extent.apply(this, arguments));
31472     });
31473   };
31474
31475   function scale(transform, k) {
31476     k = Math.max(k0, Math.min(k1, k));
31477     return k === transform.k ? transform : new Transform(k, transform.x, transform.y);
31478   }
31479
31480   function translate(transform, p0, p1) {
31481     var x = p0[0] - p1[0] * transform.k, y = p0[1] - p1[1] * transform.k;
31482     return x === transform.x && y === transform.y ? transform : new Transform(transform.k, x, y);
31483   }
31484
31485   function constrain(transform, extent) {
31486     var dx = Math.min(0, transform.invertX(extent[0][0]) - x0) || Math.max(0, transform.invertX(extent[1][0]) - x1),
31487         dy = Math.min(0, transform.invertY(extent[0][1]) - y0) || Math.max(0, transform.invertY(extent[1][1]) - y1);
31488     return dx || dy ? transform.translate(dx, dy) : transform;
31489   }
31490
31491   function centroid(extent) {
31492     return [(+extent[0][0] + +extent[1][0]) / 2, (+extent[0][1] + +extent[1][1]) / 2];
31493   }
31494
31495   function schedule(transition$$1, transform, center) {
31496     transition$$1
31497         .on("start.zoom", function() { gesture(this, arguments).start(); })
31498         .on("interrupt.zoom end.zoom", function() { gesture(this, arguments).end(); })
31499         .tween("zoom", function() {
31500           var that = this,
31501               args = arguments,
31502               g = gesture(that, args),
31503               e = extent.apply(that, args),
31504               p = center || centroid(e),
31505               w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]),
31506               a = that.__zoom,
31507               b = typeof transform === "function" ? transform.apply(that, args) : transform,
31508               i = interpolateZoom(a.invert(p).concat(w / a.k), b.invert(p).concat(w / b.k));
31509           return function(t) {
31510             if (t === 1) t = b; // Avoid rounding error on end.
31511             else { var l = i(t), k = w / l[2]; t = new Transform(k, p[0] - l[0] * k, p[1] - l[1] * k); }
31512             g.zoom(null, t);
31513           };
31514         });
31515   }
31516
31517   function gesture(that, args) {
31518     for (var i = 0, n = gestures.length, g; i < n; ++i) {
31519       if ((g = gestures[i]).that === that) {
31520         return g;
31521       }
31522     }
31523     return new Gesture(that, args);
31524   }
31525
31526   function Gesture(that, args) {
31527     this.that = that;
31528     this.args = args;
31529     this.index = -1;
31530     this.active = 0;
31531     this.extent = extent.apply(that, args);
31532   }
31533
31534   Gesture.prototype = {
31535     start: function() {
31536       if (++this.active === 1) {
31537         this.index = gestures.push(this) - 1;
31538         this.emit("start");
31539       }
31540       return this;
31541     },
31542     zoom: function(key, transform) {
31543       if (this.mouse && key !== "mouse") this.mouse[1] = transform.invert(this.mouse[0]);
31544       if (this.touch0 && key !== "touch") this.touch0[1] = transform.invert(this.touch0[0]);
31545       if (this.touch1 && key !== "touch") this.touch1[1] = transform.invert(this.touch1[0]);
31546       this.that.__zoom = transform;
31547       this.emit("zoom");
31548       return this;
31549     },
31550     end: function() {
31551       if (--this.active === 0) {
31552         gestures.splice(this.index, 1);
31553         this.index = -1;
31554         this.emit("end");
31555       }
31556       return this;
31557     },
31558     emit: function(type) {
31559       customEvent(new ZoomEvent(zoom, type, this.that.__zoom), listeners.apply, listeners, [type, this.that, this.args]);
31560     }
31561   };
31562
31563   function wheeled() {
31564     if (!filter.apply(this, arguments)) return;
31565     var g = gesture(this, arguments),
31566         t = this.__zoom,
31567         k = Math.max(k0, Math.min(k1, t.k * Math.pow(2, -event.deltaY * (event.deltaMode ? 120 : 1) / 500))),
31568         p = mouse(this);
31569
31570     // If the mouse is in the same location as before, reuse it.
31571     // If there were recent wheel events, reset the wheel idle timeout.
31572     if (g.wheel) {
31573       if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) {
31574         g.mouse[1] = t.invert(g.mouse[0] = p);
31575       }
31576       clearTimeout(g.wheel);
31577     }
31578
31579     // If this wheel event won’t trigger a transform change, ignore it.
31580     else if (t.k === k) return;
31581
31582     // Otherwise, capture the mouse point and location at the start.
31583     else {
31584       g.mouse = [p, t.invert(p)];
31585       interrupt(this);
31586       g.start();
31587     }
31588
31589     noevent$1();
31590     g.wheel = setTimeout(wheelidled, wheelDelay);
31591     g.zoom("mouse", constrain(translate(scale(t, k), g.mouse[0], g.mouse[1]), g.extent));
31592
31593     function wheelidled() {
31594       g.wheel = null;
31595       g.end();
31596     }
31597   }
31598
31599   function mousedowned() {
31600     if (touchending || !filter.apply(this, arguments)) return;
31601     var g = gesture(this, arguments),
31602         v = select(event.view).on("mousemove.zoom", mousemoved, true).on("mouseup.zoom", mouseupped, true),
31603         p = mouse(this);
31604
31605     dragDisable(event.view);
31606     nopropagation$1();
31607     g.mouse = [p, this.__zoom.invert(p)];
31608     interrupt(this);
31609     g.start();
31610
31611     function mousemoved() {
31612       noevent$1();
31613       g.moved = true;
31614       g.zoom("mouse", constrain(translate(g.that.__zoom, g.mouse[0] = mouse(g.that), g.mouse[1]), g.extent));
31615     }
31616
31617     function mouseupped() {
31618       v.on("mousemove.zoom mouseup.zoom", null);
31619       yesdrag(event.view, g.moved);
31620       noevent$1();
31621       g.end();
31622     }
31623   }
31624
31625   function dblclicked() {
31626     if (!filter.apply(this, arguments)) return;
31627     var t0 = this.__zoom,
31628         p0 = mouse(this),
31629         p1 = t0.invert(p0),
31630         k1 = t0.k * (event.shiftKey ? 0.5 : 2),
31631         t1 = constrain(translate(scale(t0, k1), p0, p1), extent.apply(this, arguments));
31632
31633     noevent$1();
31634     if (duration > 0) select(this).transition().duration(duration).call(schedule, t1, p0);
31635     else select(this).call(zoom.transform, t1);
31636   }
31637
31638   function touchstarted() {
31639     if (!filter.apply(this, arguments)) return;
31640     var g = gesture(this, arguments),
31641         touches$$1 = event.changedTouches,
31642         n = touches$$1.length, i, t, p;
31643
31644     nopropagation$1();
31645     for (i = 0; i < n; ++i) {
31646       t = touches$$1[i], p = touch(this, touches$$1, t.identifier);
31647       p = [p, this.__zoom.invert(p), t.identifier];
31648       if (!g.touch0) g.touch0 = p;
31649       else if (!g.touch1) g.touch1 = p;
31650     }
31651     if (touchstarting) {
31652       touchstarting = clearTimeout(touchstarting);
31653       if (!g.touch1) return g.end(), dblclicked.apply(this, arguments);
31654     }
31655     if (event.touches.length === n) {
31656       touchstarting = setTimeout(function() { touchstarting = null; }, touchDelay);
31657       interrupt(this);
31658       g.start();
31659     }
31660   }
31661
31662   function touchmoved() {
31663     var g = gesture(this, arguments),
31664         touches$$1 = event.changedTouches,
31665         n = touches$$1.length, i, t, p, l;
31666
31667     noevent$1();
31668     if (touchstarting) touchstarting = clearTimeout(touchstarting);
31669     for (i = 0; i < n; ++i) {
31670       t = touches$$1[i], p = touch(this, touches$$1, t.identifier);
31671       if (g.touch0 && g.touch0[2] === t.identifier) g.touch0[0] = p;
31672       else if (g.touch1 && g.touch1[2] === t.identifier) g.touch1[0] = p;
31673     }
31674     t = g.that.__zoom;
31675     if (g.touch1) {
31676       var p0 = g.touch0[0], l0 = g.touch0[1],
31677           p1 = g.touch1[0], l1 = g.touch1[1],
31678           dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp,
31679           dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl;
31680       t = scale(t, Math.sqrt(dp / dl));
31681       p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2];
31682       l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];
31683     }
31684     else if (g.touch0) p = g.touch0[0], l = g.touch0[1];
31685     else return;
31686     g.zoom("touch", constrain(translate(t, p, l), g.extent));
31687   }
31688
31689   function touchended() {
31690     var g = gesture(this, arguments),
31691         touches$$1 = event.changedTouches,
31692         n = touches$$1.length, i, t;
31693
31694     nopropagation$1();
31695     if (touchending) clearTimeout(touchending);
31696     touchending = setTimeout(function() { touchending = null; }, touchDelay);
31697     for (i = 0; i < n; ++i) {
31698       t = touches$$1[i];
31699       if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0;
31700       else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1;
31701     }
31702     if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1;
31703     if (!g.touch0) g.end();
31704   }
31705
31706   zoom.filter = function(_) {
31707     return arguments.length ? (filter = typeof _ === "function" ? _ : constant$10(!!_), zoom) : filter;
31708   };
31709
31710   zoom.extent = function(_) {
31711     return arguments.length ? (extent = typeof _ === "function" ? _ : constant$10([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom) : extent;
31712   };
31713
31714   zoom.scaleExtent = function(_) {
31715     return arguments.length ? (k0 = +_[0], k1 = +_[1], zoom) : [k0, k1];
31716   };
31717
31718   zoom.translateExtent = function(_) {
31719     return arguments.length ? (x0 = +_[0][0], x1 = +_[1][0], y0 = +_[0][1], y1 = +_[1][1], zoom) : [[x0, y0], [x1, y1]];
31720   };
31721
31722   zoom.duration = function(_) {
31723     return arguments.length ? (duration = +_, zoom) : duration;
31724   };
31725
31726   zoom.on = function() {
31727     var value = listeners.on.apply(listeners, arguments);
31728     return value === listeners ? zoom : value;
31729   };
31730
31731   return zoom;
31732 };
31733
31734 var constant$11 = function(x) {
31735   return function() {
31736     return x;
31737   };
31738 };
31739
31740 var BrushEvent = function(target, type, selection) {
31741   this.target = target;
31742   this.type = type;
31743   this.selection = selection;
31744 };
31745
31746 function nopropagation$2() {
31747   event.stopImmediatePropagation();
31748 }
31749
31750 var noevent$2 = function() {
31751   event.preventDefault();
31752   event.stopImmediatePropagation();
31753 };
31754
31755 var MODE_DRAG = {name: "drag"};
31756 var MODE_SPACE = {name: "space"};
31757 var MODE_HANDLE = {name: "handle"};
31758 var MODE_CENTER = {name: "center"};
31759
31760 var X = {
31761   name: "x",
31762   handles: ["e", "w"].map(type$3),
31763   input: function(x, e) { return x && [[x[0], e[0][1]], [x[1], e[1][1]]]; },
31764   output: function(xy) { return xy && [xy[0][0], xy[1][0]]; }
31765 };
31766
31767 var Y = {
31768   name: "y",
31769   handles: ["n", "s"].map(type$3),
31770   input: function(y, e) { return y && [[e[0][0], y[0]], [e[1][0], y[1]]]; },
31771   output: function(xy) { return xy && [xy[0][1], xy[1][1]]; }
31772 };
31773
31774 var XY = {
31775   name: "xy",
31776   handles: ["n", "e", "s", "w", "nw", "ne", "se", "sw"].map(type$3),
31777   input: function(xy) { return xy; },
31778   output: function(xy) { return xy; }
31779 };
31780
31781 var cursors = {
31782   overlay: "crosshair",
31783   selection: "move",
31784   n: "ns-resize",
31785   e: "ew-resize",
31786   s: "ns-resize",
31787   w: "ew-resize",
31788   nw: "nwse-resize",
31789   ne: "nesw-resize",
31790   se: "nwse-resize",
31791   sw: "nesw-resize"
31792 };
31793
31794 var flipX = {
31795   e: "w",
31796   w: "e",
31797   nw: "ne",
31798   ne: "nw",
31799   se: "sw",
31800   sw: "se"
31801 };
31802
31803 var flipY = {
31804   n: "s",
31805   s: "n",
31806   nw: "sw",
31807   ne: "se",
31808   se: "ne",
31809   sw: "nw"
31810 };
31811
31812 var signsX = {
31813   overlay: +1,
31814   selection: +1,
31815   n: null,
31816   e: +1,
31817   s: null,
31818   w: -1,
31819   nw: -1,
31820   ne: +1,
31821   se: +1,
31822   sw: -1
31823 };
31824
31825 var signsY = {
31826   overlay: +1,
31827   selection: +1,
31828   n: -1,
31829   e: null,
31830   s: +1,
31831   w: null,
31832   nw: -1,
31833   ne: -1,
31834   se: +1,
31835   sw: +1
31836 };
31837
31838 function type$3(t) {
31839   return {type: t};
31840 }
31841
31842 // Ignore right-click, since that should open the context menu.
31843 function defaultFilter$2() {
31844   return !event.button;
31845 }
31846
31847 function defaultExtent$1() {
31848   var svg = this.ownerSVGElement || this;
31849   return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]];
31850 }
31851
31852 // Like d3.local, but with the name “__brush” rather than auto-generated.
31853 function local$1(node) {
31854   while (!node.__brush) if (!(node = node.parentNode)) return;
31855   return node.__brush;
31856 }
31857
31858 function empty$1(extent) {
31859   return extent[0][0] === extent[1][0]
31860       || extent[0][1] === extent[1][1];
31861 }
31862
31863 function brushSelection(node) {
31864   var state = node.__brush;
31865   return state ? state.dim.output(state.selection) : null;
31866 }
31867
31868 function brushX() {
31869   return brush$1(X);
31870 }
31871
31872 function brushY() {
31873   return brush$1(Y);
31874 }
31875
31876 var brush = function() {
31877   return brush$1(XY);
31878 };
31879
31880 function brush$1(dim) {
31881   var extent = defaultExtent$1,
31882       filter = defaultFilter$2,
31883       listeners = dispatch(brush, "start", "brush", "end"),
31884       handleSize = 6,
31885       touchending;
31886
31887   function brush(group) {
31888     var overlay = group
31889         .property("__brush", initialize)
31890       .selectAll(".overlay")
31891       .data([type$3("overlay")]);
31892
31893     overlay.enter().append("rect")
31894         .attr("class", "overlay")
31895         .attr("pointer-events", "all")
31896         .attr("cursor", cursors.overlay)
31897       .merge(overlay)
31898         .each(function() {
31899           var extent = local$1(this).extent;
31900           select(this)
31901               .attr("x", extent[0][0])
31902               .attr("y", extent[0][1])
31903               .attr("width", extent[1][0] - extent[0][0])
31904               .attr("height", extent[1][1] - extent[0][1]);
31905         });
31906
31907     group.selectAll(".selection")
31908       .data([type$3("selection")])
31909       .enter().append("rect")
31910         .attr("class", "selection")
31911         .attr("cursor", cursors.selection)
31912         .attr("fill", "#777")
31913         .attr("fill-opacity", 0.3)
31914         .attr("stroke", "#fff")
31915         .attr("shape-rendering", "crispEdges");
31916
31917     var handle = group.selectAll(".handle")
31918       .data(dim.handles, function(d) { return d.type; });
31919
31920     handle.exit().remove();
31921
31922     handle.enter().append("rect")
31923         .attr("class", function(d) { return "handle handle--" + d.type; })
31924         .attr("cursor", function(d) { return cursors[d.type]; });
31925
31926     group
31927         .each(redraw)
31928         .attr("fill", "none")
31929         .attr("pointer-events", "all")
31930         .style("-webkit-tap-highlight-color", "rgba(0,0,0,0)")
31931         .on("mousedown.brush touchstart.brush", started);
31932   }
31933
31934   brush.move = function(group, selection$$1) {
31935     if (group.selection) {
31936       group
31937           .on("start.brush", function() { emitter(this, arguments).beforestart().start(); })
31938           .on("interrupt.brush end.brush", function() { emitter(this, arguments).end(); })
31939           .tween("brush", function() {
31940             var that = this,
31941                 state = that.__brush,
31942                 emit = emitter(that, arguments),
31943                 selection0 = state.selection,
31944                 selection1 = dim.input(typeof selection$$1 === "function" ? selection$$1.apply(this, arguments) : selection$$1, state.extent),
31945                 i = interpolate(selection0, selection1);
31946
31947             function tween(t) {
31948               state.selection = t === 1 && empty$1(selection1) ? null : i(t);
31949               redraw.call(that);
31950               emit.brush();
31951             }
31952
31953             return selection0 && selection1 ? tween : tween(1);
31954           });
31955     } else {
31956       group
31957           .each(function() {
31958             var that = this,
31959                 args = arguments,
31960                 state = that.__brush,
31961                 selection1 = dim.input(typeof selection$$1 === "function" ? selection$$1.apply(that, args) : selection$$1, state.extent),
31962                 emit = emitter(that, args).beforestart();
31963
31964             interrupt(that);
31965             state.selection = selection1 == null || empty$1(selection1) ? null : selection1;
31966             redraw.call(that);
31967             emit.start().brush().end();
31968           });
31969     }
31970   };
31971
31972   function redraw() {
31973     var group = select(this),
31974         selection$$1 = local$1(this).selection;
31975
31976     if (selection$$1) {
31977       group.selectAll(".selection")
31978           .style("display", null)
31979           .attr("x", selection$$1[0][0])
31980           .attr("y", selection$$1[0][1])
31981           .attr("width", selection$$1[1][0] - selection$$1[0][0])
31982           .attr("height", selection$$1[1][1] - selection$$1[0][1]);
31983
31984       group.selectAll(".handle")
31985           .style("display", null)
31986           .attr("x", function(d) { return d.type[d.type.length - 1] === "e" ? selection$$1[1][0] - handleSize / 2 : selection$$1[0][0] - handleSize / 2; })
31987           .attr("y", function(d) { return d.type[0] === "s" ? selection$$1[1][1] - handleSize / 2 : selection$$1[0][1] - handleSize / 2; })
31988           .attr("width", function(d) { return d.type === "n" || d.type === "s" ? selection$$1[1][0] - selection$$1[0][0] + handleSize : handleSize; })
31989           .attr("height", function(d) { return d.type === "e" || d.type === "w" ? selection$$1[1][1] - selection$$1[0][1] + handleSize : handleSize; });
31990     }
31991
31992     else {
31993       group.selectAll(".selection,.handle")
31994           .style("display", "none")
31995           .attr("x", null)
31996           .attr("y", null)
31997           .attr("width", null)
31998           .attr("height", null);
31999     }
32000   }
32001
32002   function emitter(that, args) {
32003     return that.__brush.emitter || new Emitter(that, args);
32004   }
32005
32006   function Emitter(that, args) {
32007     this.that = that;
32008     this.args = args;
32009     this.state = that.__brush;
32010     this.active = 0;
32011   }
32012
32013   Emitter.prototype = {
32014     beforestart: function() {
32015       if (++this.active === 1) this.state.emitter = this, this.starting = true;
32016       return this;
32017     },
32018     start: function() {
32019       if (this.starting) this.starting = false, this.emit("start");
32020       return this;
32021     },
32022     brush: function() {
32023       this.emit("brush");
32024       return this;
32025     },
32026     end: function() {
32027       if (--this.active === 0) delete this.state.emitter, this.emit("end");
32028       return this;
32029     },
32030     emit: function(type) {
32031       customEvent(new BrushEvent(brush, type, dim.output(this.state.selection)), listeners.apply, listeners, [type, this.that, this.args]);
32032     }
32033   };
32034
32035   function started() {
32036     if (event.touches) { if (event.changedTouches.length < event.touches.length) return noevent$2(); }
32037     else if (touchending) return;
32038     if (!filter.apply(this, arguments)) return;
32039
32040     var that = this,
32041         type = event.target.__data__.type,
32042         mode = (event.metaKey ? type = "overlay" : type) === "selection" ? MODE_DRAG : (event.altKey ? MODE_CENTER : MODE_HANDLE),
32043         signX = dim === Y ? null : signsX[type],
32044         signY = dim === X ? null : signsY[type],
32045         state = local$1(that),
32046         extent = state.extent,
32047         selection$$1 = state.selection,
32048         W = extent[0][0], w0, w1,
32049         N = extent[0][1], n0, n1,
32050         E = extent[1][0], e0, e1,
32051         S = extent[1][1], s0, s1,
32052         dx,
32053         dy,
32054         moving,
32055         shifting = signX && signY && event.shiftKey,
32056         lockX,
32057         lockY,
32058         point0 = mouse(that),
32059         point = point0,
32060         emit = emitter(that, arguments).beforestart();
32061
32062     if (type === "overlay") {
32063       state.selection = selection$$1 = [
32064         [w0 = dim === Y ? W : point0[0], n0 = dim === X ? N : point0[1]],
32065         [e0 = dim === Y ? E : w0, s0 = dim === X ? S : n0]
32066       ];
32067     } else {
32068       w0 = selection$$1[0][0];
32069       n0 = selection$$1[0][1];
32070       e0 = selection$$1[1][0];
32071       s0 = selection$$1[1][1];
32072     }
32073
32074     w1 = w0;
32075     n1 = n0;
32076     e1 = e0;
32077     s1 = s0;
32078
32079     var group = select(that)
32080         .attr("pointer-events", "none");
32081
32082     var overlay = group.selectAll(".overlay")
32083         .attr("cursor", cursors[type]);
32084
32085     if (event.touches) {
32086       group
32087           .on("touchmove.brush", moved, true)
32088           .on("touchend.brush touchcancel.brush", ended, true);
32089     } else {
32090       var view = select(event.view)
32091           .on("keydown.brush", keydowned, true)
32092           .on("keyup.brush", keyupped, true)
32093           .on("mousemove.brush", moved, true)
32094           .on("mouseup.brush", ended, true);
32095
32096       dragDisable(event.view);
32097     }
32098
32099     nopropagation$2();
32100     interrupt(that);
32101     redraw.call(that);
32102     emit.start();
32103
32104     function moved() {
32105       var point1 = mouse(that);
32106       if (shifting && !lockX && !lockY) {
32107         if (Math.abs(point1[0] - point[0]) > Math.abs(point1[1] - point[1])) lockY = true;
32108         else lockX = true;
32109       }
32110       point = point1;
32111       moving = true;
32112       noevent$2();
32113       move();
32114     }
32115
32116     function move() {
32117       var t;
32118
32119       dx = point[0] - point0[0];
32120       dy = point[1] - point0[1];
32121
32122       switch (mode) {
32123         case MODE_SPACE:
32124         case MODE_DRAG: {
32125           if (signX) dx = Math.max(W - w0, Math.min(E - e0, dx)), w1 = w0 + dx, e1 = e0 + dx;
32126           if (signY) dy = Math.max(N - n0, Math.min(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy;
32127           break;
32128         }
32129         case MODE_HANDLE: {
32130           if (signX < 0) dx = Math.max(W - w0, Math.min(E - w0, dx)), w1 = w0 + dx, e1 = e0;
32131           else if (signX > 0) dx = Math.max(W - e0, Math.min(E - e0, dx)), w1 = w0, e1 = e0 + dx;
32132           if (signY < 0) dy = Math.max(N - n0, Math.min(S - n0, dy)), n1 = n0 + dy, s1 = s0;
32133           else if (signY > 0) dy = Math.max(N - s0, Math.min(S - s0, dy)), n1 = n0, s1 = s0 + dy;
32134           break;
32135         }
32136         case MODE_CENTER: {
32137           if (signX) w1 = Math.max(W, Math.min(E, w0 - dx * signX)), e1 = Math.max(W, Math.min(E, e0 + dx * signX));
32138           if (signY) n1 = Math.max(N, Math.min(S, n0 - dy * signY)), s1 = Math.max(N, Math.min(S, s0 + dy * signY));
32139           break;
32140         }
32141       }
32142
32143       if (e1 < w1) {
32144         signX *= -1;
32145         t = w0, w0 = e0, e0 = t;
32146         t = w1, w1 = e1, e1 = t;
32147         if (type in flipX) overlay.attr("cursor", cursors[type = flipX[type]]);
32148       }
32149
32150       if (s1 < n1) {
32151         signY *= -1;
32152         t = n0, n0 = s0, s0 = t;
32153         t = n1, n1 = s1, s1 = t;
32154         if (type in flipY) overlay.attr("cursor", cursors[type = flipY[type]]);
32155       }
32156
32157       if (state.selection) selection$$1 = state.selection; // May be set by brush.move!
32158       if (lockX) w1 = selection$$1[0][0], e1 = selection$$1[1][0];
32159       if (lockY) n1 = selection$$1[0][1], s1 = selection$$1[1][1];
32160
32161       if (selection$$1[0][0] !== w1
32162           || selection$$1[0][1] !== n1
32163           || selection$$1[1][0] !== e1
32164           || selection$$1[1][1] !== s1) {
32165         state.selection = [[w1, n1], [e1, s1]];
32166         redraw.call(that);
32167         emit.brush();
32168       }
32169     }
32170
32171     function ended() {
32172       nopropagation$2();
32173       if (event.touches) {
32174         if (event.touches.length) return;
32175         if (touchending) clearTimeout(touchending);
32176         touchending = setTimeout(function() { touchending = null; }, 500); // Ghost clicks are delayed!
32177         group.on("touchmove.brush touchend.brush touchcancel.brush", null);
32178       } else {
32179         yesdrag(event.view, moving);
32180         view.on("keydown.brush keyup.brush mousemove.brush mouseup.brush", null);
32181       }
32182       group.attr("pointer-events", "all");
32183       overlay.attr("cursor", cursors.overlay);
32184       if (state.selection) selection$$1 = state.selection; // May be set by brush.move (on start)!
32185       if (empty$1(selection$$1)) state.selection = null, redraw.call(that);
32186       emit.end();
32187     }
32188
32189     function keydowned() {
32190       switch (event.keyCode) {
32191         case 16: { // SHIFT
32192           shifting = signX && signY;
32193           break;
32194         }
32195         case 18: { // ALT
32196           if (mode === MODE_HANDLE) {
32197             if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
32198             if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
32199             mode = MODE_CENTER;
32200             move();
32201           }
32202           break;
32203         }
32204         case 32: { // SPACE; takes priority over ALT
32205           if (mode === MODE_HANDLE || mode === MODE_CENTER) {
32206             if (signX < 0) e0 = e1 - dx; else if (signX > 0) w0 = w1 - dx;
32207             if (signY < 0) s0 = s1 - dy; else if (signY > 0) n0 = n1 - dy;
32208             mode = MODE_SPACE;
32209             overlay.attr("cursor", cursors.selection);
32210             move();
32211           }
32212           break;
32213         }
32214         default: return;
32215       }
32216       noevent$2();
32217     }
32218
32219     function keyupped() {
32220       switch (event.keyCode) {
32221         case 16: { // SHIFT
32222           if (shifting) {
32223             lockX = lockY = shifting = false;
32224             move();
32225           }
32226           break;
32227         }
32228         case 18: { // ALT
32229           if (mode === MODE_CENTER) {
32230             if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1;
32231             if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1;
32232             mode = MODE_HANDLE;
32233             move();
32234           }
32235           break;
32236         }
32237         case 32: { // SPACE
32238           if (mode === MODE_SPACE) {
32239             if (event.altKey) {
32240               if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;
32241               if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;
32242               mode = MODE_CENTER;
32243             } else {
32244               if (signX < 0) e0 = e1; else if (signX > 0) w0 = w1;
32245               if (signY < 0) s0 = s1; else if (signY > 0) n0 = n1;
32246               mode = MODE_HANDLE;
32247             }
32248             overlay.attr("cursor", cursors[type]);
32249             move();
32250           }
32251           break;
32252         }
32253         default: return;
32254       }
32255       noevent$2();
32256     }
32257   }
32258
32259   function initialize() {
32260     var state = this.__brush || {selection: null};
32261     state.extent = extent.apply(this, arguments);
32262     state.dim = dim;
32263     return state;
32264   }
32265
32266   brush.extent = function(_) {
32267     return arguments.length ? (extent = typeof _ === "function" ? _ : constant$11([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), brush) : extent;
32268   };
32269
32270   brush.filter = function(_) {
32271     return arguments.length ? (filter = typeof _ === "function" ? _ : constant$11(!!_), brush) : filter;
32272   };
32273
32274   brush.handleSize = function(_) {
32275     return arguments.length ? (handleSize = +_, brush) : handleSize;
32276   };
32277
32278   brush.on = function() {
32279     var value = listeners.on.apply(listeners, arguments);
32280     return value === listeners ? brush : value;
32281   };
32282
32283   return brush;
32284 }
32285
32286 var cos = Math.cos;
32287 var sin = Math.sin;
32288 var pi$3 = Math.PI;
32289 var halfPi$2 = pi$3 / 2;
32290 var tau$3 = pi$3 * 2;
32291 var max$1 = Math.max;
32292
32293 function compareValue(compare) {
32294   return function(a, b) {
32295     return compare(
32296       a.source.value + a.target.value,
32297       b.source.value + b.target.value
32298     );
32299   };
32300 }
32301
32302 var chord = function() {
32303   var padAngle = 0,
32304       sortGroups = null,
32305       sortSubgroups = null,
32306       sortChords = null;
32307
32308   function chord(matrix) {
32309     var n = matrix.length,
32310         groupSums = [],
32311         groupIndex = range(n),
32312         subgroupIndex = [],
32313         chords = [],
32314         groups = chords.groups = new Array(n),
32315         subgroups = new Array(n * n),
32316         k,
32317         x,
32318         x0,
32319         dx,
32320         i,
32321         j;
32322
32323     // Compute the sum.
32324     k = 0, i = -1; while (++i < n) {
32325       x = 0, j = -1; while (++j < n) {
32326         x += matrix[i][j];
32327       }
32328       groupSums.push(x);
32329       subgroupIndex.push(range(n));
32330       k += x;
32331     }
32332
32333     // Sort groups…
32334     if (sortGroups) groupIndex.sort(function(a, b) {
32335       return sortGroups(groupSums[a], groupSums[b]);
32336     });
32337
32338     // Sort subgroups…
32339     if (sortSubgroups) subgroupIndex.forEach(function(d, i) {
32340       d.sort(function(a, b) {
32341         return sortSubgroups(matrix[i][a], matrix[i][b]);
32342       });
32343     });
32344
32345     // Convert the sum to scaling factor for [0, 2pi].
32346     // TODO Allow start and end angle to be specified?
32347     // TODO Allow padding to be specified as percentage?
32348     k = max$1(0, tau$3 - padAngle * n) / k;
32349     dx = k ? padAngle : tau$3 / n;
32350
32351     // Compute the start and end angle for each group and subgroup.
32352     // Note: Opera has a bug reordering object literal properties!
32353     x = 0, i = -1; while (++i < n) {
32354       x0 = x, j = -1; while (++j < n) {
32355         var di = groupIndex[i],
32356             dj = subgroupIndex[di][j],
32357             v = matrix[di][dj],
32358             a0 = x,
32359             a1 = x += v * k;
32360         subgroups[dj * n + di] = {
32361           index: di,
32362           subindex: dj,
32363           startAngle: a0,
32364           endAngle: a1,
32365           value: v
32366         };
32367       }
32368       groups[di] = {
32369         index: di,
32370         startAngle: x0,
32371         endAngle: x,
32372         value: groupSums[di]
32373       };
32374       x += dx;
32375     }
32376
32377     // Generate chords for each (non-empty) subgroup-subgroup link.
32378     i = -1; while (++i < n) {
32379       j = i - 1; while (++j < n) {
32380         var source = subgroups[j * n + i],
32381             target = subgroups[i * n + j];
32382         if (source.value || target.value) {
32383           chords.push(source.value < target.value
32384               ? {source: target, target: source}
32385               : {source: source, target: target});
32386         }
32387       }
32388     }
32389
32390     return sortChords ? chords.sort(sortChords) : chords;
32391   }
32392
32393   chord.padAngle = function(_) {
32394     return arguments.length ? (padAngle = max$1(0, _), chord) : padAngle;
32395   };
32396
32397   chord.sortGroups = function(_) {
32398     return arguments.length ? (sortGroups = _, chord) : sortGroups;
32399   };
32400
32401   chord.sortSubgroups = function(_) {
32402     return arguments.length ? (sortSubgroups = _, chord) : sortSubgroups;
32403   };
32404
32405   chord.sortChords = function(_) {
32406     return arguments.length ? (_ == null ? sortChords = null : (sortChords = compareValue(_))._ = _, chord) : sortChords && sortChords._;
32407   };
32408
32409   return chord;
32410 };
32411
32412 var slice$5 = Array.prototype.slice;
32413
32414 var constant$12 = function(x) {
32415   return function() {
32416     return x;
32417   };
32418 };
32419
32420 function defaultSource(d) {
32421   return d.source;
32422 }
32423
32424 function defaultTarget(d) {
32425   return d.target;
32426 }
32427
32428 function defaultRadius$1(d) {
32429   return d.radius;
32430 }
32431
32432 function defaultStartAngle(d) {
32433   return d.startAngle;
32434 }
32435
32436 function defaultEndAngle(d) {
32437   return d.endAngle;
32438 }
32439
32440 var ribbon = function() {
32441   var source = defaultSource,
32442       target = defaultTarget,
32443       radius = defaultRadius$1,
32444       startAngle = defaultStartAngle,
32445       endAngle = defaultEndAngle,
32446       context = null;
32447
32448   function ribbon() {
32449     var buffer,
32450         argv = slice$5.call(arguments),
32451         s = source.apply(this, argv),
32452         t = target.apply(this, argv),
32453         sr = +radius.apply(this, (argv[0] = s, argv)),
32454         sa0 = startAngle.apply(this, argv) - halfPi$2,
32455         sa1 = endAngle.apply(this, argv) - halfPi$2,
32456         sx0 = sr * cos(sa0),
32457         sy0 = sr * sin(sa0),
32458         tr = +radius.apply(this, (argv[0] = t, argv)),
32459         ta0 = startAngle.apply(this, argv) - halfPi$2,
32460         ta1 = endAngle.apply(this, argv) - halfPi$2;
32461
32462     if (!context) context = buffer = path();
32463
32464     context.moveTo(sx0, sy0);
32465     context.arc(0, 0, sr, sa0, sa1);
32466     if (sa0 !== ta0 || sa1 !== ta1) { // TODO sr !== tr?
32467       context.quadraticCurveTo(0, 0, tr * cos(ta0), tr * sin(ta0));
32468       context.arc(0, 0, tr, ta0, ta1);
32469     }
32470     context.quadraticCurveTo(0, 0, sx0, sy0);
32471     context.closePath();
32472
32473     if (buffer) return context = null, buffer + "" || null;
32474   }
32475
32476   ribbon.radius = function(_) {
32477     return arguments.length ? (radius = typeof _ === "function" ? _ : constant$12(+_), ribbon) : radius;
32478   };
32479
32480   ribbon.startAngle = function(_) {
32481     return arguments.length ? (startAngle = typeof _ === "function" ? _ : constant$12(+_), ribbon) : startAngle;
32482   };
32483
32484   ribbon.endAngle = function(_) {
32485     return arguments.length ? (endAngle = typeof _ === "function" ? _ : constant$12(+_), ribbon) : endAngle;
32486   };
32487
32488   ribbon.source = function(_) {
32489     return arguments.length ? (source = _, ribbon) : source;
32490   };
32491
32492   ribbon.target = function(_) {
32493     return arguments.length ? (target = _, ribbon) : target;
32494   };
32495
32496   ribbon.context = function(_) {
32497     return arguments.length ? ((context = _ == null ? null : _), ribbon) : context;
32498   };
32499
32500   return ribbon;
32501 };
32502
32503 // Adds floating point numbers with twice the normal precision.
32504 // Reference: J. R. Shewchuk, Adaptive Precision Floating-Point Arithmetic and
32505 // Fast Robust Geometric Predicates, Discrete & Computational Geometry 18(3)
32506 // 305–363 (1997).
32507 // Code adapted from GeographicLib by Charles F. F. Karney,
32508 // http://geographiclib.sourceforge.net/
32509
32510 var adder = function() {
32511   return new Adder;
32512 };
32513
32514 function Adder() {
32515   this.reset();
32516 }
32517
32518 Adder.prototype = {
32519   constructor: Adder,
32520   reset: function() {
32521     this.s = // rounded value
32522     this.t = 0; // exact error
32523   },
32524   add: function(y) {
32525     add$1(temp, y, this.t);
32526     add$1(this, temp.s, this.s);
32527     if (this.s) this.t += temp.t;
32528     else this.s = temp.t;
32529   },
32530   valueOf: function() {
32531     return this.s;
32532   }
32533 };
32534
32535 var temp = new Adder;
32536
32537 function add$1(adder, a, b) {
32538   var x = adder.s = a + b,
32539       bv = x - a,
32540       av = x - bv;
32541   adder.t = (a - av) + (b - bv);
32542 }
32543
32544 var epsilon$4 = 1e-6;
32545 var epsilon2$2 = 1e-12;
32546 var pi$4 = Math.PI;
32547 var halfPi$3 = pi$4 / 2;
32548 var quarterPi = pi$4 / 4;
32549 var tau$4 = pi$4 * 2;
32550
32551 var degrees$1 = 180 / pi$4;
32552 var radians = pi$4 / 180;
32553
32554 var abs = Math.abs;
32555 var atan = Math.atan;
32556 var atan2 = Math.atan2;
32557 var cos$1 = Math.cos;
32558 var ceil = Math.ceil;
32559 var exp = Math.exp;
32560
32561 var log$1 = Math.log;
32562 var pow$1 = Math.pow;
32563 var sin$1 = Math.sin;
32564 var sign$1 = Math.sign || function(x) { return x > 0 ? 1 : x < 0 ? -1 : 0; };
32565 var sqrt$1 = Math.sqrt;
32566 var tan = Math.tan;
32567
32568 function acos(x) {
32569   return x > 1 ? 0 : x < -1 ? pi$4 : Math.acos(x);
32570 }
32571
32572 function asin$1(x) {
32573   return x > 1 ? halfPi$3 : x < -1 ? -halfPi$3 : Math.asin(x);
32574 }
32575
32576 function haversin(x) {
32577   return (x = sin$1(x / 2)) * x;
32578 }
32579
32580 function noop$2() {}
32581
32582 function streamGeometry(geometry, stream) {
32583   if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) {
32584     streamGeometryType[geometry.type](geometry, stream);
32585   }
32586 }
32587
32588 var streamObjectType = {
32589   Feature: function(feature, stream) {
32590     streamGeometry(feature.geometry, stream);
32591   },
32592   FeatureCollection: function(object, stream) {
32593     var features = object.features, i = -1, n = features.length;
32594     while (++i < n) streamGeometry(features[i].geometry, stream);
32595   }
32596 };
32597
32598 var streamGeometryType = {
32599   Sphere: function(object, stream) {
32600     stream.sphere();
32601   },
32602   Point: function(object, stream) {
32603     object = object.coordinates;
32604     stream.point(object[0], object[1], object[2]);
32605   },
32606   MultiPoint: function(object, stream) {
32607     var coordinates = object.coordinates, i = -1, n = coordinates.length;
32608     while (++i < n) object = coordinates[i], stream.point(object[0], object[1], object[2]);
32609   },
32610   LineString: function(object, stream) {
32611     streamLine(object.coordinates, stream, 0);
32612   },
32613   MultiLineString: function(object, stream) {
32614     var coordinates = object.coordinates, i = -1, n = coordinates.length;
32615     while (++i < n) streamLine(coordinates[i], stream, 0);
32616   },
32617   Polygon: function(object, stream) {
32618     streamPolygon(object.coordinates, stream);
32619   },
32620   MultiPolygon: function(object, stream) {
32621     var coordinates = object.coordinates, i = -1, n = coordinates.length;
32622     while (++i < n) streamPolygon(coordinates[i], stream);
32623   },
32624   GeometryCollection: function(object, stream) {
32625     var geometries = object.geometries, i = -1, n = geometries.length;
32626     while (++i < n) streamGeometry(geometries[i], stream);
32627   }
32628 };
32629
32630 function streamLine(coordinates, stream, closed) {
32631   var i = -1, n = coordinates.length - closed, coordinate;
32632   stream.lineStart();
32633   while (++i < n) coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]);
32634   stream.lineEnd();
32635 }
32636
32637 function streamPolygon(coordinates, stream) {
32638   var i = -1, n = coordinates.length;
32639   stream.polygonStart();
32640   while (++i < n) streamLine(coordinates[i], stream, 1);
32641   stream.polygonEnd();
32642 }
32643
32644 var geoStream = function(object, stream) {
32645   if (object && streamObjectType.hasOwnProperty(object.type)) {
32646     streamObjectType[object.type](object, stream);
32647   } else {
32648     streamGeometry(object, stream);
32649   }
32650 };
32651
32652 var areaRingSum = adder();
32653
32654 var areaSum = adder();
32655 var lambda00;
32656 var phi00;
32657 var lambda0;
32658 var cosPhi0;
32659 var sinPhi0;
32660
32661 var areaStream = {
32662   point: noop$2,
32663   lineStart: noop$2,
32664   lineEnd: noop$2,
32665   polygonStart: function() {
32666     areaRingSum.reset();
32667     areaStream.lineStart = areaRingStart;
32668     areaStream.lineEnd = areaRingEnd;
32669   },
32670   polygonEnd: function() {
32671     var areaRing = +areaRingSum;
32672     areaSum.add(areaRing < 0 ? tau$4 + areaRing : areaRing);
32673     this.lineStart = this.lineEnd = this.point = noop$2;
32674   },
32675   sphere: function() {
32676     areaSum.add(tau$4);
32677   }
32678 };
32679
32680 function areaRingStart() {
32681   areaStream.point = areaPointFirst;
32682 }
32683
32684 function areaRingEnd() {
32685   areaPoint(lambda00, phi00);
32686 }
32687
32688 function areaPointFirst(lambda, phi) {
32689   areaStream.point = areaPoint;
32690   lambda00 = lambda, phi00 = phi;
32691   lambda *= radians, phi *= radians;
32692   lambda0 = lambda, cosPhi0 = cos$1(phi = phi / 2 + quarterPi), sinPhi0 = sin$1(phi);
32693 }
32694
32695 function areaPoint(lambda, phi) {
32696   lambda *= radians, phi *= radians;
32697   phi = phi / 2 + quarterPi; // half the angular distance from south pole
32698
32699   // Spherical excess E for a spherical triangle with vertices: south pole,
32700   // previous point, current point.  Uses a formula derived from Cagnoli’s
32701   // theorem.  See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2).
32702   var dLambda = lambda - lambda0,
32703       sdLambda = dLambda >= 0 ? 1 : -1,
32704       adLambda = sdLambda * dLambda,
32705       cosPhi = cos$1(phi),
32706       sinPhi = sin$1(phi),
32707       k = sinPhi0 * sinPhi,
32708       u = cosPhi0 * cosPhi + k * cos$1(adLambda),
32709       v = k * sdLambda * sin$1(adLambda);
32710   areaRingSum.add(atan2(v, u));
32711
32712   // Advance the previous points.
32713   lambda0 = lambda, cosPhi0 = cosPhi, sinPhi0 = sinPhi;
32714 }
32715
32716 var area$1 = function(object) {
32717   areaSum.reset();
32718   geoStream(object, areaStream);
32719   return areaSum * 2;
32720 };
32721
32722 function spherical(cartesian) {
32723   return [atan2(cartesian[1], cartesian[0]), asin$1(cartesian[2])];
32724 }
32725
32726 function cartesian(spherical) {
32727   var lambda = spherical[0], phi = spherical[1], cosPhi = cos$1(phi);
32728   return [cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi)];
32729 }
32730
32731 function cartesianDot(a, b) {
32732   return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
32733 }
32734
32735 function cartesianCross(a, b) {
32736   return [a[1] * b[2] - a[2] * b[1], a[2] * b[0] - a[0] * b[2], a[0] * b[1] - a[1] * b[0]];
32737 }
32738
32739 // TODO return a
32740 function cartesianAddInPlace(a, b) {
32741   a[0] += b[0], a[1] += b[1], a[2] += b[2];
32742 }
32743
32744 function cartesianScale(vector, k) {
32745   return [vector[0] * k, vector[1] * k, vector[2] * k];
32746 }
32747
32748 // TODO return d
32749 function cartesianNormalizeInPlace(d) {
32750   var l = sqrt$1(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
32751   d[0] /= l, d[1] /= l, d[2] /= l;
32752 }
32753
32754 var lambda0$1;
32755 var phi0;
32756 var lambda1;
32757 var phi1;
32758 var lambda2;
32759 var lambda00$1;
32760 var phi00$1;
32761 var p0;
32762 var deltaSum = adder();
32763 var ranges;
32764 var range$1;
32765
32766 var boundsStream = {
32767   point: boundsPoint,
32768   lineStart: boundsLineStart,
32769   lineEnd: boundsLineEnd,
32770   polygonStart: function() {
32771     boundsStream.point = boundsRingPoint;
32772     boundsStream.lineStart = boundsRingStart;
32773     boundsStream.lineEnd = boundsRingEnd;
32774     deltaSum.reset();
32775     areaStream.polygonStart();
32776   },
32777   polygonEnd: function() {
32778     areaStream.polygonEnd();
32779     boundsStream.point = boundsPoint;
32780     boundsStream.lineStart = boundsLineStart;
32781     boundsStream.lineEnd = boundsLineEnd;
32782     if (areaRingSum < 0) lambda0$1 = -(lambda1 = 180), phi0 = -(phi1 = 90);
32783     else if (deltaSum > epsilon$4) phi1 = 90;
32784     else if (deltaSum < -epsilon$4) phi0 = -90;
32785     range$1[0] = lambda0$1, range$1[1] = lambda1;
32786   }
32787 };
32788
32789 function boundsPoint(lambda, phi) {
32790   ranges.push(range$1 = [lambda0$1 = lambda, lambda1 = lambda]);
32791   if (phi < phi0) phi0 = phi;
32792   if (phi > phi1) phi1 = phi;
32793 }
32794
32795 function linePoint(lambda, phi) {
32796   var p = cartesian([lambda * radians, phi * radians]);
32797   if (p0) {
32798     var normal = cartesianCross(p0, p),
32799         equatorial = [normal[1], -normal[0], 0],
32800         inflection = cartesianCross(equatorial, normal);
32801     cartesianNormalizeInPlace(inflection);
32802     inflection = spherical(inflection);
32803     var delta = lambda - lambda2,
32804         sign$$1 = delta > 0 ? 1 : -1,
32805         lambdai = inflection[0] * degrees$1 * sign$$1,
32806         phii,
32807         antimeridian = abs(delta) > 180;
32808     if (antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) {
32809       phii = inflection[1] * degrees$1;
32810       if (phii > phi1) phi1 = phii;
32811     } else if (lambdai = (lambdai + 360) % 360 - 180, antimeridian ^ (sign$$1 * lambda2 < lambdai && lambdai < sign$$1 * lambda)) {
32812       phii = -inflection[1] * degrees$1;
32813       if (phii < phi0) phi0 = phii;
32814     } else {
32815       if (phi < phi0) phi0 = phi;
32816       if (phi > phi1) phi1 = phi;
32817     }
32818     if (antimeridian) {
32819       if (lambda < lambda2) {
32820         if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda;
32821       } else {
32822         if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda;
32823       }
32824     } else {
32825       if (lambda1 >= lambda0$1) {
32826         if (lambda < lambda0$1) lambda0$1 = lambda;
32827         if (lambda > lambda1) lambda1 = lambda;
32828       } else {
32829         if (lambda > lambda2) {
32830           if (angle(lambda0$1, lambda) > angle(lambda0$1, lambda1)) lambda1 = lambda;
32831         } else {
32832           if (angle(lambda, lambda1) > angle(lambda0$1, lambda1)) lambda0$1 = lambda;
32833         }
32834       }
32835     }
32836   } else {
32837     boundsPoint(lambda, phi);
32838   }
32839   p0 = p, lambda2 = lambda;
32840 }
32841
32842 function boundsLineStart() {
32843   boundsStream.point = linePoint;
32844 }
32845
32846 function boundsLineEnd() {
32847   range$1[0] = lambda0$1, range$1[1] = lambda1;
32848   boundsStream.point = boundsPoint;
32849   p0 = null;
32850 }
32851
32852 function boundsRingPoint(lambda, phi) {
32853   if (p0) {
32854     var delta = lambda - lambda2;
32855     deltaSum.add(abs(delta) > 180 ? delta + (delta > 0 ? 360 : -360) : delta);
32856   } else {
32857     lambda00$1 = lambda, phi00$1 = phi;
32858   }
32859   areaStream.point(lambda, phi);
32860   linePoint(lambda, phi);
32861 }
32862
32863 function boundsRingStart() {
32864   areaStream.lineStart();
32865 }
32866
32867 function boundsRingEnd() {
32868   boundsRingPoint(lambda00$1, phi00$1);
32869   areaStream.lineEnd();
32870   if (abs(deltaSum) > epsilon$4) lambda0$1 = -(lambda1 = 180);
32871   range$1[0] = lambda0$1, range$1[1] = lambda1;
32872   p0 = null;
32873 }
32874
32875 // Finds the left-right distance between two longitudes.
32876 // This is almost the same as (lambda1 - lambda0 + 360°) % 360°, except that we want
32877 // the distance between ±180° to be 360°.
32878 function angle(lambda0, lambda1) {
32879   return (lambda1 -= lambda0) < 0 ? lambda1 + 360 : lambda1;
32880 }
32881
32882 function rangeCompare(a, b) {
32883   return a[0] - b[0];
32884 }
32885
32886 function rangeContains(range, x) {
32887   return range[0] <= range[1] ? range[0] <= x && x <= range[1] : x < range[0] || range[1] < x;
32888 }
32889
32890 var bounds = function(feature) {
32891   var i, n, a, b, merged, deltaMax, delta;
32892
32893   phi1 = lambda1 = -(lambda0$1 = phi0 = Infinity);
32894   ranges = [];
32895   geoStream(feature, boundsStream);
32896
32897   // First, sort ranges by their minimum longitudes.
32898   if (n = ranges.length) {
32899     ranges.sort(rangeCompare);
32900
32901     // Then, merge any ranges that overlap.
32902     for (i = 1, a = ranges[0], merged = [a]; i < n; ++i) {
32903       b = ranges[i];
32904       if (rangeContains(a, b[0]) || rangeContains(a, b[1])) {
32905         if (angle(a[0], b[1]) > angle(a[0], a[1])) a[1] = b[1];
32906         if (angle(b[0], a[1]) > angle(a[0], a[1])) a[0] = b[0];
32907       } else {
32908         merged.push(a = b);
32909       }
32910     }
32911
32912     // Finally, find the largest gap between the merged ranges.
32913     // The final bounding box will be the inverse of this gap.
32914     for (deltaMax = -Infinity, n = merged.length - 1, i = 0, a = merged[n]; i <= n; a = b, ++i) {
32915       b = merged[i];
32916       if ((delta = angle(a[1], b[0])) > deltaMax) deltaMax = delta, lambda0$1 = b[0], lambda1 = a[1];
32917     }
32918   }
32919
32920   ranges = range$1 = null;
32921
32922   return lambda0$1 === Infinity || phi0 === Infinity
32923       ? [[NaN, NaN], [NaN, NaN]]
32924       : [[lambda0$1, phi0], [lambda1, phi1]];
32925 };
32926
32927 var W0;
32928 var W1;
32929 var X0;
32930 var Y0;
32931 var Z0;
32932 var X1;
32933 var Y1;
32934 var Z1;
32935 var X2;
32936 var Y2;
32937 var Z2;
32938 var lambda00$2;
32939 var phi00$2;
32940 var x0;
32941 var y0;
32942 var z0; // previous point
32943
32944 var centroidStream = {
32945   sphere: noop$2,
32946   point: centroidPoint,
32947   lineStart: centroidLineStart,
32948   lineEnd: centroidLineEnd,
32949   polygonStart: function() {
32950     centroidStream.lineStart = centroidRingStart;
32951     centroidStream.lineEnd = centroidRingEnd;
32952   },
32953   polygonEnd: function() {
32954     centroidStream.lineStart = centroidLineStart;
32955     centroidStream.lineEnd = centroidLineEnd;
32956   }
32957 };
32958
32959 // Arithmetic mean of Cartesian vectors.
32960 function centroidPoint(lambda, phi) {
32961   lambda *= radians, phi *= radians;
32962   var cosPhi = cos$1(phi);
32963   centroidPointCartesian(cosPhi * cos$1(lambda), cosPhi * sin$1(lambda), sin$1(phi));
32964 }
32965
32966 function centroidPointCartesian(x, y, z) {
32967   ++W0;
32968   X0 += (x - X0) / W0;
32969   Y0 += (y - Y0) / W0;
32970   Z0 += (z - Z0) / W0;
32971 }
32972
32973 function centroidLineStart() {
32974   centroidStream.point = centroidLinePointFirst;
32975 }
32976
32977 function centroidLinePointFirst(lambda, phi) {
32978   lambda *= radians, phi *= radians;
32979   var cosPhi = cos$1(phi);
32980   x0 = cosPhi * cos$1(lambda);
32981   y0 = cosPhi * sin$1(lambda);
32982   z0 = sin$1(phi);
32983   centroidStream.point = centroidLinePoint;
32984   centroidPointCartesian(x0, y0, z0);
32985 }
32986
32987 function centroidLinePoint(lambda, phi) {
32988   lambda *= radians, phi *= radians;
32989   var cosPhi = cos$1(phi),
32990       x = cosPhi * cos$1(lambda),
32991       y = cosPhi * sin$1(lambda),
32992       z = sin$1(phi),
32993       w = atan2(sqrt$1((w = y0 * z - z0 * y) * w + (w = z0 * x - x0 * z) * w + (w = x0 * y - y0 * x) * w), x0 * x + y0 * y + z0 * z);
32994   W1 += w;
32995   X1 += w * (x0 + (x0 = x));
32996   Y1 += w * (y0 + (y0 = y));
32997   Z1 += w * (z0 + (z0 = z));
32998   centroidPointCartesian(x0, y0, z0);
32999 }
33000
33001 function centroidLineEnd() {
33002   centroidStream.point = centroidPoint;
33003 }
33004
33005 // See J. E. Brock, The Inertia Tensor for a Spherical Triangle,
33006 // J. Applied Mechanics 42, 239 (1975).
33007 function centroidRingStart() {
33008   centroidStream.point = centroidRingPointFirst;
33009 }
33010
33011 function centroidRingEnd() {
33012   centroidRingPoint(lambda00$2, phi00$2);
33013   centroidStream.point = centroidPoint;
33014 }
33015
33016 function centroidRingPointFirst(lambda, phi) {
33017   lambda00$2 = lambda, phi00$2 = phi;
33018   lambda *= radians, phi *= radians;
33019   centroidStream.point = centroidRingPoint;
33020   var cosPhi = cos$1(phi);
33021   x0 = cosPhi * cos$1(lambda);
33022   y0 = cosPhi * sin$1(lambda);
33023   z0 = sin$1(phi);
33024   centroidPointCartesian(x0, y0, z0);
33025 }
33026
33027 function centroidRingPoint(lambda, phi) {
33028   lambda *= radians, phi *= radians;
33029   var cosPhi = cos$1(phi),
33030       x = cosPhi * cos$1(lambda),
33031       y = cosPhi * sin$1(lambda),
33032       z = sin$1(phi),
33033       cx = y0 * z - z0 * y,
33034       cy = z0 * x - x0 * z,
33035       cz = x0 * y - y0 * x,
33036       m = sqrt$1(cx * cx + cy * cy + cz * cz),
33037       u = x0 * x + y0 * y + z0 * z,
33038       v = m && -acos(u) / m, // area weight
33039       w = atan2(m, u); // line weight
33040   X2 += v * cx;
33041   Y2 += v * cy;
33042   Z2 += v * cz;
33043   W1 += w;
33044   X1 += w * (x0 + (x0 = x));
33045   Y1 += w * (y0 + (y0 = y));
33046   Z1 += w * (z0 + (z0 = z));
33047   centroidPointCartesian(x0, y0, z0);
33048 }
33049
33050 var d3GeoCentroid = function(object) {
33051   W0 = W1 =
33052   X0 = Y0 = Z0 =
33053   X1 = Y1 = Z1 =
33054   X2 = Y2 = Z2 = 0;
33055   geoStream(object, centroidStream);
33056
33057   var x = X2,
33058       y = Y2,
33059       z = Z2,
33060       m = x * x + y * y + z * z;
33061
33062   // If the area-weighted ccentroid is undefined, fall back to length-weighted ccentroid.
33063   if (m < epsilon2$2) {
33064     x = X1, y = Y1, z = Z1;
33065     // If the feature has zero length, fall back to arithmetic mean of point vectors.
33066     if (W1 < epsilon$4) x = X0, y = Y0, z = Z0;
33067     m = x * x + y * y + z * z;
33068     // If the feature still has an undefined ccentroid, then return.
33069     if (m < epsilon2$2) return [NaN, NaN];
33070   }
33071
33072   return [atan2(y, x) * degrees$1, asin$1(z / sqrt$1(m)) * degrees$1];
33073 };
33074
33075 var constant$13 = function(x) {
33076   return function() {
33077     return x;
33078   };
33079 };
33080
33081 var compose = function(a, b) {
33082
33083   function compose(x, y) {
33084     return x = a(x, y), b(x[0], x[1]);
33085   }
33086
33087   if (a.invert && b.invert) compose.invert = function(x, y) {
33088     return x = b.invert(x, y), x && a.invert(x[0], x[1]);
33089   };
33090
33091   return compose;
33092 };
33093
33094 function rotationIdentity(lambda, phi) {
33095   return [lambda > pi$4 ? lambda - tau$4 : lambda < -pi$4 ? lambda + tau$4 : lambda, phi];
33096 }
33097
33098 rotationIdentity.invert = rotationIdentity;
33099
33100 function rotateRadians(deltaLambda, deltaPhi, deltaGamma) {
33101   return (deltaLambda %= tau$4) ? (deltaPhi || deltaGamma ? compose(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma))
33102     : rotationLambda(deltaLambda))
33103     : (deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma)
33104     : rotationIdentity);
33105 }
33106
33107 function forwardRotationLambda(deltaLambda) {
33108   return function(lambda, phi) {
33109     return lambda += deltaLambda, [lambda > pi$4 ? lambda - tau$4 : lambda < -pi$4 ? lambda + tau$4 : lambda, phi];
33110   };
33111 }
33112
33113 function rotationLambda(deltaLambda) {
33114   var rotation = forwardRotationLambda(deltaLambda);
33115   rotation.invert = forwardRotationLambda(-deltaLambda);
33116   return rotation;
33117 }
33118
33119 function rotationPhiGamma(deltaPhi, deltaGamma) {
33120   var cosDeltaPhi = cos$1(deltaPhi),
33121       sinDeltaPhi = sin$1(deltaPhi),
33122       cosDeltaGamma = cos$1(deltaGamma),
33123       sinDeltaGamma = sin$1(deltaGamma);
33124
33125   function rotation(lambda, phi) {
33126     var cosPhi = cos$1(phi),
33127         x = cos$1(lambda) * cosPhi,
33128         y = sin$1(lambda) * cosPhi,
33129         z = sin$1(phi),
33130         k = z * cosDeltaPhi + x * sinDeltaPhi;
33131     return [
33132       atan2(y * cosDeltaGamma - k * sinDeltaGamma, x * cosDeltaPhi - z * sinDeltaPhi),
33133       asin$1(k * cosDeltaGamma + y * sinDeltaGamma)
33134     ];
33135   }
33136
33137   rotation.invert = function(lambda, phi) {
33138     var cosPhi = cos$1(phi),
33139         x = cos$1(lambda) * cosPhi,
33140         y = sin$1(lambda) * cosPhi,
33141         z = sin$1(phi),
33142         k = z * cosDeltaGamma - y * sinDeltaGamma;
33143     return [
33144       atan2(y * cosDeltaGamma + z * sinDeltaGamma, x * cosDeltaPhi + k * sinDeltaPhi),
33145       asin$1(k * cosDeltaPhi - x * sinDeltaPhi)
33146     ];
33147   };
33148
33149   return rotation;
33150 }
33151
33152 var rotation = function(rotate) {
33153   rotate = rotateRadians(rotate[0] * radians, rotate[1] * radians, rotate.length > 2 ? rotate[2] * radians : 0);
33154
33155   function forward(coordinates) {
33156     coordinates = rotate(coordinates[0] * radians, coordinates[1] * radians);
33157     return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates;
33158   }
33159
33160   forward.invert = function(coordinates) {
33161     coordinates = rotate.invert(coordinates[0] * radians, coordinates[1] * radians);
33162     return coordinates[0] *= degrees$1, coordinates[1] *= degrees$1, coordinates;
33163   };
33164
33165   return forward;
33166 };
33167
33168 // Generates a circle centered at [0°, 0°], with a given radius and precision.
33169 function circleStream(stream, radius, delta, direction, t0, t1) {
33170   if (!delta) return;
33171   var cosRadius = cos$1(radius),
33172       sinRadius = sin$1(radius),
33173       step = direction * delta;
33174   if (t0 == null) {
33175     t0 = radius + direction * tau$4;
33176     t1 = radius - step / 2;
33177   } else {
33178     t0 = circleRadius(cosRadius, t0);
33179     t1 = circleRadius(cosRadius, t1);
33180     if (direction > 0 ? t0 < t1 : t0 > t1) t0 += direction * tau$4;
33181   }
33182   for (var point, t = t0; direction > 0 ? t > t1 : t < t1; t -= step) {
33183     point = spherical([cosRadius, -sinRadius * cos$1(t), -sinRadius * sin$1(t)]);
33184     stream.point(point[0], point[1]);
33185   }
33186 }
33187
33188 // Returns the signed angle of a cartesian point relative to [cosRadius, 0, 0].
33189 function circleRadius(cosRadius, point) {
33190   point = cartesian(point), point[0] -= cosRadius;
33191   cartesianNormalizeInPlace(point);
33192   var radius = acos(-point[1]);
33193   return ((-point[2] < 0 ? -radius : radius) + tau$4 - epsilon$4) % tau$4;
33194 }
33195
33196 var circle$1 = function() {
33197   var center = constant$13([0, 0]),
33198       radius = constant$13(90),
33199       precision = constant$13(6),
33200       ring,
33201       rotate,
33202       stream = {point: point};
33203
33204   function point(x, y) {
33205     ring.push(x = rotate(x, y));
33206     x[0] *= degrees$1, x[1] *= degrees$1;
33207   }
33208
33209   function circle() {
33210     var c = center.apply(this, arguments),
33211         r = radius.apply(this, arguments) * radians,
33212         p = precision.apply(this, arguments) * radians;
33213     ring = [];
33214     rotate = rotateRadians(-c[0] * radians, -c[1] * radians, 0).invert;
33215     circleStream(stream, r, p, 1);
33216     c = {type: "Polygon", coordinates: [ring]};
33217     ring = rotate = null;
33218     return c;
33219   }
33220
33221   circle.center = function(_) {
33222     return arguments.length ? (center = typeof _ === "function" ? _ : constant$13([+_[0], +_[1]]), circle) : center;
33223   };
33224
33225   circle.radius = function(_) {
33226     return arguments.length ? (radius = typeof _ === "function" ? _ : constant$13(+_), circle) : radius;
33227   };
33228
33229   circle.precision = function(_) {
33230     return arguments.length ? (precision = typeof _ === "function" ? _ : constant$13(+_), circle) : precision;
33231   };
33232
33233   return circle;
33234 };
33235
33236 var clipBuffer = function() {
33237   var lines = [],
33238       line;
33239   return {
33240     point: function(x, y) {
33241       line.push([x, y]);
33242     },
33243     lineStart: function() {
33244       lines.push(line = []);
33245     },
33246     lineEnd: noop$2,
33247     rejoin: function() {
33248       if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));
33249     },
33250     result: function() {
33251       var result = lines;
33252       lines = [];
33253       line = null;
33254       return result;
33255     }
33256   };
33257 };
33258
33259 var clipLine = function(a, b, x0, y0, x1, y1) {
33260   var ax = a[0],
33261       ay = a[1],
33262       bx = b[0],
33263       by = b[1],
33264       t0 = 0,
33265       t1 = 1,
33266       dx = bx - ax,
33267       dy = by - ay,
33268       r;
33269
33270   r = x0 - ax;
33271   if (!dx && r > 0) return;
33272   r /= dx;
33273   if (dx < 0) {
33274     if (r < t0) return;
33275     if (r < t1) t1 = r;
33276   } else if (dx > 0) {
33277     if (r > t1) return;
33278     if (r > t0) t0 = r;
33279   }
33280
33281   r = x1 - ax;
33282   if (!dx && r < 0) return;
33283   r /= dx;
33284   if (dx < 0) {
33285     if (r > t1) return;
33286     if (r > t0) t0 = r;
33287   } else if (dx > 0) {
33288     if (r < t0) return;
33289     if (r < t1) t1 = r;
33290   }
33291
33292   r = y0 - ay;
33293   if (!dy && r > 0) return;
33294   r /= dy;
33295   if (dy < 0) {
33296     if (r < t0) return;
33297     if (r < t1) t1 = r;
33298   } else if (dy > 0) {
33299     if (r > t1) return;
33300     if (r > t0) t0 = r;
33301   }
33302
33303   r = y1 - ay;
33304   if (!dy && r < 0) return;
33305   r /= dy;
33306   if (dy < 0) {
33307     if (r > t1) return;
33308     if (r > t0) t0 = r;
33309   } else if (dy > 0) {
33310     if (r < t0) return;
33311     if (r < t1) t1 = r;
33312   }
33313
33314   if (t0 > 0) a[0] = ax + t0 * dx, a[1] = ay + t0 * dy;
33315   if (t1 < 1) b[0] = ax + t1 * dx, b[1] = ay + t1 * dy;
33316   return true;
33317 };
33318
33319 var pointEqual = function(a, b) {
33320   return abs(a[0] - b[0]) < epsilon$4 && abs(a[1] - b[1]) < epsilon$4;
33321 };
33322
33323 function Intersection(point, points, other, entry) {
33324   this.x = point;
33325   this.z = points;
33326   this.o = other; // another intersection
33327   this.e = entry; // is an entry?
33328   this.v = false; // visited
33329   this.n = this.p = null; // next & previous
33330 }
33331
33332 // A generalized polygon clipping algorithm: given a polygon that has been cut
33333 // into its visible line segments, and rejoins the segments by interpolating
33334 // along the clip edge.
33335 var clipPolygon = function(segments, compareIntersection, startInside, interpolate, stream) {
33336   var subject = [],
33337       clip = [],
33338       i,
33339       n;
33340
33341   segments.forEach(function(segment) {
33342     if ((n = segment.length - 1) <= 0) return;
33343     var n, p0 = segment[0], p1 = segment[n], x;
33344
33345     // If the first and last points of a segment are coincident, then treat as a
33346     // closed ring. TODO if all rings are closed, then the winding order of the
33347     // exterior ring should be checked.
33348     if (pointEqual(p0, p1)) {
33349       stream.lineStart();
33350       for (i = 0; i < n; ++i) stream.point((p0 = segment[i])[0], p0[1]);
33351       stream.lineEnd();
33352       return;
33353     }
33354
33355     subject.push(x = new Intersection(p0, segment, null, true));
33356     clip.push(x.o = new Intersection(p0, null, x, false));
33357     subject.push(x = new Intersection(p1, segment, null, false));
33358     clip.push(x.o = new Intersection(p1, null, x, true));
33359   });
33360
33361   if (!subject.length) return;
33362
33363   clip.sort(compareIntersection);
33364   link$1(subject);
33365   link$1(clip);
33366
33367   for (i = 0, n = clip.length; i < n; ++i) {
33368     clip[i].e = startInside = !startInside;
33369   }
33370
33371   var start = subject[0],
33372       points,
33373       point;
33374
33375   while (1) {
33376     // Find first unvisited intersection.
33377     var current = start,
33378         isSubject = true;
33379     while (current.v) if ((current = current.n) === start) return;
33380     points = current.z;
33381     stream.lineStart();
33382     do {
33383       current.v = current.o.v = true;
33384       if (current.e) {
33385         if (isSubject) {
33386           for (i = 0, n = points.length; i < n; ++i) stream.point((point = points[i])[0], point[1]);
33387         } else {
33388           interpolate(current.x, current.n.x, 1, stream);
33389         }
33390         current = current.n;
33391       } else {
33392         if (isSubject) {
33393           points = current.p.z;
33394           for (i = points.length - 1; i >= 0; --i) stream.point((point = points[i])[0], point[1]);
33395         } else {
33396           interpolate(current.x, current.p.x, -1, stream);
33397         }
33398         current = current.p;
33399       }
33400       current = current.o;
33401       points = current.z;
33402       isSubject = !isSubject;
33403     } while (!current.v);
33404     stream.lineEnd();
33405   }
33406 };
33407
33408 function link$1(array) {
33409   if (!(n = array.length)) return;
33410   var n,
33411       i = 0,
33412       a = array[0],
33413       b;
33414   while (++i < n) {
33415     a.n = b = array[i];
33416     b.p = a;
33417     a = b;
33418   }
33419   a.n = b = array[0];
33420   b.p = a;
33421 }
33422
33423 var clipMax = 1e9;
33424 var clipMin = -clipMax;
33425
33426 // TODO Use d3-polygon’s polygonContains here for the ring check?
33427 // TODO Eliminate duplicate buffering in clipBuffer and polygon.push?
33428
33429 function clipExtent(x0, y0, x1, y1) {
33430
33431   function visible(x, y) {
33432     return x0 <= x && x <= x1 && y0 <= y && y <= y1;
33433   }
33434
33435   function interpolate(from, to, direction, stream) {
33436     var a = 0, a1 = 0;
33437     if (from == null
33438         || (a = corner(from, direction)) !== (a1 = corner(to, direction))
33439         || comparePoint(from, to) < 0 ^ direction > 0) {
33440       do stream.point(a === 0 || a === 3 ? x0 : x1, a > 1 ? y1 : y0);
33441       while ((a = (a + direction + 4) % 4) !== a1);
33442     } else {
33443       stream.point(to[0], to[1]);
33444     }
33445   }
33446
33447   function corner(p, direction) {
33448     return abs(p[0] - x0) < epsilon$4 ? direction > 0 ? 0 : 3
33449         : abs(p[0] - x1) < epsilon$4 ? direction > 0 ? 2 : 1
33450         : abs(p[1] - y0) < epsilon$4 ? direction > 0 ? 1 : 0
33451         : direction > 0 ? 3 : 2; // abs(p[1] - y1) < epsilon
33452   }
33453
33454   function compareIntersection(a, b) {
33455     return comparePoint(a.x, b.x);
33456   }
33457
33458   function comparePoint(a, b) {
33459     var ca = corner(a, 1),
33460         cb = corner(b, 1);
33461     return ca !== cb ? ca - cb
33462         : ca === 0 ? b[1] - a[1]
33463         : ca === 1 ? a[0] - b[0]
33464         : ca === 2 ? a[1] - b[1]
33465         : b[0] - a[0];
33466   }
33467
33468   return function(stream) {
33469     var activeStream = stream,
33470         bufferStream = clipBuffer(),
33471         segments,
33472         polygon,
33473         ring,
33474         x__, y__, v__, // first point
33475         x_, y_, v_, // previous point
33476         first,
33477         clean;
33478
33479     var clipStream = {
33480       point: point,
33481       lineStart: lineStart,
33482       lineEnd: lineEnd,
33483       polygonStart: polygonStart,
33484       polygonEnd: polygonEnd
33485     };
33486
33487     function point(x, y) {
33488       if (visible(x, y)) activeStream.point(x, y);
33489     }
33490
33491     function polygonInside() {
33492       var winding = 0;
33493
33494       for (var i = 0, n = polygon.length; i < n; ++i) {
33495         for (var ring = polygon[i], j = 1, m = ring.length, point = ring[0], a0, a1, b0 = point[0], b1 = point[1]; j < m; ++j) {
33496           a0 = b0, a1 = b1, point = ring[j], b0 = point[0], b1 = point[1];
33497           if (a1 <= y1) { if (b1 > y1 && (b0 - a0) * (y1 - a1) > (b1 - a1) * (x0 - a0)) ++winding; }
33498           else { if (b1 <= y1 && (b0 - a0) * (y1 - a1) < (b1 - a1) * (x0 - a0)) --winding; }
33499         }
33500       }
33501
33502       return winding;
33503     }
33504
33505     // Buffer geometry within a polygon and then clip it en masse.
33506     function polygonStart() {
33507       activeStream = bufferStream, segments = [], polygon = [], clean = true;
33508     }
33509
33510     function polygonEnd() {
33511       var startInside = polygonInside(),
33512           cleanInside = clean && startInside,
33513           visible = (segments = merge(segments)).length;
33514       if (cleanInside || visible) {
33515         stream.polygonStart();
33516         if (cleanInside) {
33517           stream.lineStart();
33518           interpolate(null, null, 1, stream);
33519           stream.lineEnd();
33520         }
33521         if (visible) {
33522           clipPolygon(segments, compareIntersection, startInside, interpolate, stream);
33523         }
33524         stream.polygonEnd();
33525       }
33526       activeStream = stream, segments = polygon = ring = null;
33527     }
33528
33529     function lineStart() {
33530       clipStream.point = linePoint;
33531       if (polygon) polygon.push(ring = []);
33532       first = true;
33533       v_ = false;
33534       x_ = y_ = NaN;
33535     }
33536
33537     // TODO rather than special-case polygons, simply handle them separately.
33538     // Ideally, coincident intersection points should be jittered to avoid
33539     // clipping issues.
33540     function lineEnd() {
33541       if (segments) {
33542         linePoint(x__, y__);
33543         if (v__ && v_) bufferStream.rejoin();
33544         segments.push(bufferStream.result());
33545       }
33546       clipStream.point = point;
33547       if (v_) activeStream.lineEnd();
33548     }
33549
33550     function linePoint(x, y) {
33551       var v = visible(x, y);
33552       if (polygon) ring.push([x, y]);
33553       if (first) {
33554         x__ = x, y__ = y, v__ = v;
33555         first = false;
33556         if (v) {
33557           activeStream.lineStart();
33558           activeStream.point(x, y);
33559         }
33560       } else {
33561         if (v && v_) activeStream.point(x, y);
33562         else {
33563           var a = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))],
33564               b = [x = Math.max(clipMin, Math.min(clipMax, x)), y = Math.max(clipMin, Math.min(clipMax, y))];
33565           if (clipLine(a, b, x0, y0, x1, y1)) {
33566             if (!v_) {
33567               activeStream.lineStart();
33568               activeStream.point(a[0], a[1]);
33569             }
33570             activeStream.point(b[0], b[1]);
33571             if (!v) activeStream.lineEnd();
33572             clean = false;
33573           } else if (v) {
33574             activeStream.lineStart();
33575             activeStream.point(x, y);
33576             clean = false;
33577           }
33578         }
33579       }
33580       x_ = x, y_ = y, v_ = v;
33581     }
33582
33583     return clipStream;
33584   };
33585 }
33586
33587 var extent$1 = function() {
33588   var x0 = 0,
33589       y0 = 0,
33590       x1 = 960,
33591       y1 = 500,
33592       cache,
33593       cacheStream,
33594       clip;
33595
33596   return clip = {
33597     stream: function(stream) {
33598       return cache && cacheStream === stream ? cache : cache = clipExtent(x0, y0, x1, y1)(cacheStream = stream);
33599     },
33600     extent: function(_) {
33601       return arguments.length ? (x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1], cache = cacheStream = null, clip) : [[x0, y0], [x1, y1]];
33602     }
33603   };
33604 };
33605
33606 var lengthSum = adder();
33607 var lambda0$2;
33608 var sinPhi0$1;
33609 var cosPhi0$1;
33610
33611 var lengthStream = {
33612   sphere: noop$2,
33613   point: noop$2,
33614   lineStart: lengthLineStart,
33615   lineEnd: noop$2,
33616   polygonStart: noop$2,
33617   polygonEnd: noop$2
33618 };
33619
33620 function lengthLineStart() {
33621   lengthStream.point = lengthPointFirst;
33622   lengthStream.lineEnd = lengthLineEnd;
33623 }
33624
33625 function lengthLineEnd() {
33626   lengthStream.point = lengthStream.lineEnd = noop$2;
33627 }
33628
33629 function lengthPointFirst(lambda, phi) {
33630   lambda *= radians, phi *= radians;
33631   lambda0$2 = lambda, sinPhi0$1 = sin$1(phi), cosPhi0$1 = cos$1(phi);
33632   lengthStream.point = lengthPoint;
33633 }
33634
33635 function lengthPoint(lambda, phi) {
33636   lambda *= radians, phi *= radians;
33637   var sinPhi = sin$1(phi),
33638       cosPhi = cos$1(phi),
33639       delta = abs(lambda - lambda0$2),
33640       cosDelta = cos$1(delta),
33641       sinDelta = sin$1(delta),
33642       x = cosPhi * sinDelta,
33643       y = cosPhi0$1 * sinPhi - sinPhi0$1 * cosPhi * cosDelta,
33644       z = sinPhi0$1 * sinPhi + cosPhi0$1 * cosPhi * cosDelta;
33645   lengthSum.add(atan2(sqrt$1(x * x + y * y), z));
33646   lambda0$2 = lambda, sinPhi0$1 = sinPhi, cosPhi0$1 = cosPhi;
33647 }
33648
33649 var d3GeoLength = function(object) {
33650   lengthSum.reset();
33651   geoStream(object, lengthStream);
33652   return +lengthSum;
33653 };
33654
33655 var coordinates = [null, null];
33656 var object$1 = {type: "LineString", coordinates: coordinates};
33657
33658 var distance = function(a, b) {
33659   coordinates[0] = a;
33660   coordinates[1] = b;
33661   return d3GeoLength(object$1);
33662 };
33663
33664 function graticuleX(y0, y1, dy) {
33665   var y = range(y0, y1 - epsilon$4, dy).concat(y1);
33666   return function(x) { return y.map(function(y) { return [x, y]; }); };
33667 }
33668
33669 function graticuleY(x0, x1, dx) {
33670   var x = range(x0, x1 - epsilon$4, dx).concat(x1);
33671   return function(y) { return x.map(function(x) { return [x, y]; }); };
33672 }
33673
33674 function graticule() {
33675   var x1, x0, X1, X0,
33676       y1, y0, Y1, Y0,
33677       dx = 10, dy = dx, DX = 90, DY = 360,
33678       x, y, X, Y,
33679       precision = 2.5;
33680
33681   function graticule() {
33682     return {type: "MultiLineString", coordinates: lines()};
33683   }
33684
33685   function lines() {
33686     return range(ceil(X0 / DX) * DX, X1, DX).map(X)
33687         .concat(range(ceil(Y0 / DY) * DY, Y1, DY).map(Y))
33688         .concat(range(ceil(x0 / dx) * dx, x1, dx).filter(function(x) { return abs(x % DX) > epsilon$4; }).map(x))
33689         .concat(range(ceil(y0 / dy) * dy, y1, dy).filter(function(y) { return abs(y % DY) > epsilon$4; }).map(y));
33690   }
33691
33692   graticule.lines = function() {
33693     return lines().map(function(coordinates) { return {type: "LineString", coordinates: coordinates}; });
33694   };
33695
33696   graticule.outline = function() {
33697     return {
33698       type: "Polygon",
33699       coordinates: [
33700         X(X0).concat(
33701         Y(Y1).slice(1),
33702         X(X1).reverse().slice(1),
33703         Y(Y0).reverse().slice(1))
33704       ]
33705     };
33706   };
33707
33708   graticule.extent = function(_) {
33709     if (!arguments.length) return graticule.extentMinor();
33710     return graticule.extentMajor(_).extentMinor(_);
33711   };
33712
33713   graticule.extentMajor = function(_) {
33714     if (!arguments.length) return [[X0, Y0], [X1, Y1]];
33715     X0 = +_[0][0], X1 = +_[1][0];
33716     Y0 = +_[0][1], Y1 = +_[1][1];
33717     if (X0 > X1) _ = X0, X0 = X1, X1 = _;
33718     if (Y0 > Y1) _ = Y0, Y0 = Y1, Y1 = _;
33719     return graticule.precision(precision);
33720   };
33721
33722   graticule.extentMinor = function(_) {
33723     if (!arguments.length) return [[x0, y0], [x1, y1]];
33724     x0 = +_[0][0], x1 = +_[1][0];
33725     y0 = +_[0][1], y1 = +_[1][1];
33726     if (x0 > x1) _ = x0, x0 = x1, x1 = _;
33727     if (y0 > y1) _ = y0, y0 = y1, y1 = _;
33728     return graticule.precision(precision);
33729   };
33730
33731   graticule.step = function(_) {
33732     if (!arguments.length) return graticule.stepMinor();
33733     return graticule.stepMajor(_).stepMinor(_);
33734   };
33735
33736   graticule.stepMajor = function(_) {
33737     if (!arguments.length) return [DX, DY];
33738     DX = +_[0], DY = +_[1];
33739     return graticule;
33740   };
33741
33742   graticule.stepMinor = function(_) {
33743     if (!arguments.length) return [dx, dy];
33744     dx = +_[0], dy = +_[1];
33745     return graticule;
33746   };
33747
33748   graticule.precision = function(_) {
33749     if (!arguments.length) return precision;
33750     precision = +_;
33751     x = graticuleX(y0, y1, 90);
33752     y = graticuleY(x0, x1, precision);
33753     X = graticuleX(Y0, Y1, 90);
33754     Y = graticuleY(X0, X1, precision);
33755     return graticule;
33756   };
33757
33758   return graticule
33759       .extentMajor([[-180, -90 + epsilon$4], [180, 90 - epsilon$4]])
33760       .extentMinor([[-180, -80 - epsilon$4], [180, 80 + epsilon$4]]);
33761 }
33762
33763 function graticule10() {
33764   return graticule()();
33765 }
33766
33767 var interpolate$2 = function(a, b) {
33768   var x0 = a[0] * radians,
33769       y0 = a[1] * radians,
33770       x1 = b[0] * radians,
33771       y1 = b[1] * radians,
33772       cy0 = cos$1(y0),
33773       sy0 = sin$1(y0),
33774       cy1 = cos$1(y1),
33775       sy1 = sin$1(y1),
33776       kx0 = cy0 * cos$1(x0),
33777       ky0 = cy0 * sin$1(x0),
33778       kx1 = cy1 * cos$1(x1),
33779       ky1 = cy1 * sin$1(x1),
33780       d = 2 * asin$1(sqrt$1(haversin(y1 - y0) + cy0 * cy1 * haversin(x1 - x0))),
33781       k = sin$1(d);
33782
33783   var interpolate = d ? function(t) {
33784     var B = sin$1(t *= d) / k,
33785         A = sin$1(d - t) / k,
33786         x = A * kx0 + B * kx1,
33787         y = A * ky0 + B * ky1,
33788         z = A * sy0 + B * sy1;
33789     return [
33790       atan2(y, x) * degrees$1,
33791       atan2(z, sqrt$1(x * x + y * y)) * degrees$1
33792     ];
33793   } : function() {
33794     return [x0 * degrees$1, y0 * degrees$1];
33795   };
33796
33797   interpolate.distance = d;
33798
33799   return interpolate;
33800 };
33801
33802 var identity$7 = function(x) {
33803   return x;
33804 };
33805
33806 var areaSum$1 = adder();
33807 var areaRingSum$1 = adder();
33808 var x00;
33809 var y00;
33810 var x0$1;
33811 var y0$1;
33812
33813 var areaStream$1 = {
33814   point: noop$2,
33815   lineStart: noop$2,
33816   lineEnd: noop$2,
33817   polygonStart: function() {
33818     areaStream$1.lineStart = areaRingStart$1;
33819     areaStream$1.lineEnd = areaRingEnd$1;
33820   },
33821   polygonEnd: function() {
33822     areaStream$1.lineStart = areaStream$1.lineEnd = areaStream$1.point = noop$2;
33823     areaSum$1.add(abs(areaRingSum$1));
33824     areaRingSum$1.reset();
33825   },
33826   result: function() {
33827     var area = areaSum$1 / 2;
33828     areaSum$1.reset();
33829     return area;
33830   }
33831 };
33832
33833 function areaRingStart$1() {
33834   areaStream$1.point = areaPointFirst$1;
33835 }
33836
33837 function areaPointFirst$1(x, y) {
33838   areaStream$1.point = areaPoint$1;
33839   x00 = x0$1 = x, y00 = y0$1 = y;
33840 }
33841
33842 function areaPoint$1(x, y) {
33843   areaRingSum$1.add(y0$1 * x - x0$1 * y);
33844   x0$1 = x, y0$1 = y;
33845 }
33846
33847 function areaRingEnd$1() {
33848   areaPoint$1(x00, y00);
33849 }
33850
33851 var x0$2 = Infinity;
33852 var y0$2 = x0$2;
33853 var x1 = -x0$2;
33854 var y1 = x1;
33855
33856 var boundsStream$1 = {
33857   point: boundsPoint$1,
33858   lineStart: noop$2,
33859   lineEnd: noop$2,
33860   polygonStart: noop$2,
33861   polygonEnd: noop$2,
33862   result: function() {
33863     var bounds = [[x0$2, y0$2], [x1, y1]];
33864     x1 = y1 = -(y0$2 = x0$2 = Infinity);
33865     return bounds;
33866   }
33867 };
33868
33869 function boundsPoint$1(x, y) {
33870   if (x < x0$2) x0$2 = x;
33871   if (x > x1) x1 = x;
33872   if (y < y0$2) y0$2 = y;
33873   if (y > y1) y1 = y;
33874 }
33875
33876 // TODO Enforce positive area for exterior, negative area for interior?
33877
33878 var X0$1 = 0;
33879 var Y0$1 = 0;
33880 var Z0$1 = 0;
33881 var X1$1 = 0;
33882 var Y1$1 = 0;
33883 var Z1$1 = 0;
33884 var X2$1 = 0;
33885 var Y2$1 = 0;
33886 var Z2$1 = 0;
33887 var x00$1;
33888 var y00$1;
33889 var x0$3;
33890 var y0$3;
33891
33892 var centroidStream$1 = {
33893   point: centroidPoint$1,
33894   lineStart: centroidLineStart$1,
33895   lineEnd: centroidLineEnd$1,
33896   polygonStart: function() {
33897     centroidStream$1.lineStart = centroidRingStart$1;
33898     centroidStream$1.lineEnd = centroidRingEnd$1;
33899   },
33900   polygonEnd: function() {
33901     centroidStream$1.point = centroidPoint$1;
33902     centroidStream$1.lineStart = centroidLineStart$1;
33903     centroidStream$1.lineEnd = centroidLineEnd$1;
33904   },
33905   result: function() {
33906     var centroid = Z2$1 ? [X2$1 / Z2$1, Y2$1 / Z2$1]
33907         : Z1$1 ? [X1$1 / Z1$1, Y1$1 / Z1$1]
33908         : Z0$1 ? [X0$1 / Z0$1, Y0$1 / Z0$1]
33909         : [NaN, NaN];
33910     X0$1 = Y0$1 = Z0$1 =
33911     X1$1 = Y1$1 = Z1$1 =
33912     X2$1 = Y2$1 = Z2$1 = 0;
33913     return centroid;
33914   }
33915 };
33916
33917 function centroidPoint$1(x, y) {
33918   X0$1 += x;
33919   Y0$1 += y;
33920   ++Z0$1;
33921 }
33922
33923 function centroidLineStart$1() {
33924   centroidStream$1.point = centroidPointFirstLine;
33925 }
33926
33927 function centroidPointFirstLine(x, y) {
33928   centroidStream$1.point = centroidPointLine;
33929   centroidPoint$1(x0$3 = x, y0$3 = y);
33930 }
33931
33932 function centroidPointLine(x, y) {
33933   var dx = x - x0$3, dy = y - y0$3, z = sqrt$1(dx * dx + dy * dy);
33934   X1$1 += z * (x0$3 + x) / 2;
33935   Y1$1 += z * (y0$3 + y) / 2;
33936   Z1$1 += z;
33937   centroidPoint$1(x0$3 = x, y0$3 = y);
33938 }
33939
33940 function centroidLineEnd$1() {
33941   centroidStream$1.point = centroidPoint$1;
33942 }
33943
33944 function centroidRingStart$1() {
33945   centroidStream$1.point = centroidPointFirstRing;
33946 }
33947
33948 function centroidRingEnd$1() {
33949   centroidPointRing(x00$1, y00$1);
33950 }
33951
33952 function centroidPointFirstRing(x, y) {
33953   centroidStream$1.point = centroidPointRing;
33954   centroidPoint$1(x00$1 = x0$3 = x, y00$1 = y0$3 = y);
33955 }
33956
33957 function centroidPointRing(x, y) {
33958   var dx = x - x0$3,
33959       dy = y - y0$3,
33960       z = sqrt$1(dx * dx + dy * dy);
33961
33962   X1$1 += z * (x0$3 + x) / 2;
33963   Y1$1 += z * (y0$3 + y) / 2;
33964   Z1$1 += z;
33965
33966   z = y0$3 * x - x0$3 * y;
33967   X2$1 += z * (x0$3 + x);
33968   Y2$1 += z * (y0$3 + y);
33969   Z2$1 += z * 3;
33970   centroidPoint$1(x0$3 = x, y0$3 = y);
33971 }
33972
33973 function PathContext(context) {
33974   this._context = context;
33975 }
33976
33977 PathContext.prototype = {
33978   _radius: 4.5,
33979   pointRadius: function(_) {
33980     return this._radius = _, this;
33981   },
33982   polygonStart: function() {
33983     this._line = 0;
33984   },
33985   polygonEnd: function() {
33986     this._line = NaN;
33987   },
33988   lineStart: function() {
33989     this._point = 0;
33990   },
33991   lineEnd: function() {
33992     if (this._line === 0) this._context.closePath();
33993     this._point = NaN;
33994   },
33995   point: function(x, y) {
33996     switch (this._point) {
33997       case 0: {
33998         this._context.moveTo(x, y);
33999         this._point = 1;
34000         break;
34001       }
34002       case 1: {
34003         this._context.lineTo(x, y);
34004         break;
34005       }
34006       default: {
34007         this._context.moveTo(x + this._radius, y);
34008         this._context.arc(x, y, this._radius, 0, tau$4);
34009         break;
34010       }
34011     }
34012   },
34013   result: noop$2
34014 };
34015
34016 function PathString() {
34017   this._string = [];
34018 }
34019
34020 PathString.prototype = {
34021   _circle: circle$2(4.5),
34022   pointRadius: function(_) {
34023     return this._circle = circle$2(_), this;
34024   },
34025   polygonStart: function() {
34026     this._line = 0;
34027   },
34028   polygonEnd: function() {
34029     this._line = NaN;
34030   },
34031   lineStart: function() {
34032     this._point = 0;
34033   },
34034   lineEnd: function() {
34035     if (this._line === 0) this._string.push("Z");
34036     this._point = NaN;
34037   },
34038   point: function(x, y) {
34039     switch (this._point) {
34040       case 0: {
34041         this._string.push("M", x, ",", y);
34042         this._point = 1;
34043         break;
34044       }
34045       case 1: {
34046         this._string.push("L", x, ",", y);
34047         break;
34048       }
34049       default: {
34050         this._string.push("M", x, ",", y, this._circle);
34051         break;
34052       }
34053     }
34054   },
34055   result: function() {
34056     if (this._string.length) {
34057       var result = this._string.join("");
34058       this._string = [];
34059       return result;
34060     }
34061   }
34062 };
34063
34064 function circle$2(radius) {
34065   return "m0," + radius
34066       + "a" + radius + "," + radius + " 0 1,1 0," + -2 * radius
34067       + "a" + radius + "," + radius + " 0 1,1 0," + 2 * radius
34068       + "z";
34069 }
34070
34071 var index$5 = function(projection, context) {
34072   var pointRadius = 4.5,
34073       projectionStream,
34074       contextStream;
34075
34076   function path(object) {
34077     if (object) {
34078       if (typeof pointRadius === "function") contextStream.pointRadius(+pointRadius.apply(this, arguments));
34079       geoStream(object, projectionStream(contextStream));
34080     }
34081     return contextStream.result();
34082   }
34083
34084   path.area = function(object) {
34085     geoStream(object, projectionStream(areaStream$1));
34086     return areaStream$1.result();
34087   };
34088
34089   path.bounds = function(object) {
34090     geoStream(object, projectionStream(boundsStream$1));
34091     return boundsStream$1.result();
34092   };
34093
34094   path.centroid = function(object) {
34095     geoStream(object, projectionStream(centroidStream$1));
34096     return centroidStream$1.result();
34097   };
34098
34099   path.projection = function(_) {
34100     return arguments.length ? (projectionStream = (projection = _) == null ? identity$7 : _.stream, path) : projection;
34101   };
34102
34103   path.context = function(_) {
34104     if (!arguments.length) return context;
34105     contextStream = (context = _) == null ? new PathString : new PathContext(_);
34106     if (typeof pointRadius !== "function") contextStream.pointRadius(pointRadius);
34107     return path;
34108   };
34109
34110   path.pointRadius = function(_) {
34111     if (!arguments.length) return pointRadius;
34112     pointRadius = typeof _ === "function" ? _ : (contextStream.pointRadius(+_), +_);
34113     return path;
34114   };
34115
34116   return path.projection(projection).context(context);
34117 };
34118
34119 var sum$2 = adder();
34120
34121 var polygonContains = function(polygon, point) {
34122   var lambda = point[0],
34123       phi = point[1],
34124       normal = [sin$1(lambda), -cos$1(lambda), 0],
34125       angle = 0,
34126       winding = 0;
34127
34128   sum$2.reset();
34129
34130   for (var i = 0, n = polygon.length; i < n; ++i) {
34131     if (!(m = (ring = polygon[i]).length)) continue;
34132     var ring,
34133         m,
34134         point0 = ring[m - 1],
34135         lambda0 = point0[0],
34136         phi0 = point0[1] / 2 + quarterPi,
34137         sinPhi0 = sin$1(phi0),
34138         cosPhi0 = cos$1(phi0);
34139
34140     for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) {
34141       var point1 = ring[j],
34142           lambda1 = point1[0],
34143           phi1 = point1[1] / 2 + quarterPi,
34144           sinPhi1 = sin$1(phi1),
34145           cosPhi1 = cos$1(phi1),
34146           delta = lambda1 - lambda0,
34147           sign$$1 = delta >= 0 ? 1 : -1,
34148           absDelta = sign$$1 * delta,
34149           antimeridian = absDelta > pi$4,
34150           k = sinPhi0 * sinPhi1;
34151
34152       sum$2.add(atan2(k * sign$$1 * sin$1(absDelta), cosPhi0 * cosPhi1 + k * cos$1(absDelta)));
34153       angle += antimeridian ? delta + sign$$1 * tau$4 : delta;
34154
34155       // Are the longitudes either side of the point’s meridian (lambda),
34156       // and are the latitudes smaller than the parallel (phi)?
34157       if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) {
34158         var arc = cartesianCross(cartesian(point0), cartesian(point1));
34159         cartesianNormalizeInPlace(arc);
34160         var intersection = cartesianCross(normal, arc);
34161         cartesianNormalizeInPlace(intersection);
34162         var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin$1(intersection[2]);
34163         if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) {
34164           winding += antimeridian ^ delta >= 0 ? 1 : -1;
34165         }
34166       }
34167     }
34168   }
34169
34170   // First, determine whether the South pole is inside or outside:
34171   //
34172   // It is inside if:
34173   // * the polygon winds around it in a clockwise direction.
34174   // * the polygon does not (cumulatively) wind around it, but has a negative
34175   //   (counter-clockwise) area.
34176   //
34177   // Second, count the (signed) number of times a segment crosses a lambda
34178   // from the point to the South pole.  If it is zero, then the point is the
34179   // same side as the South pole.
34180
34181   return (angle < -epsilon$4 || angle < epsilon$4 && sum$2 < -epsilon$4) ^ (winding & 1);
34182 };
34183
34184 var clip = function(pointVisible, clipLine, interpolate, start) {
34185   return function(rotate, sink) {
34186     var line = clipLine(sink),
34187         rotatedStart = rotate.invert(start[0], start[1]),
34188         ringBuffer = clipBuffer(),
34189         ringSink = clipLine(ringBuffer),
34190         polygonStarted = false,
34191         polygon,
34192         segments,
34193         ring;
34194
34195     var clip = {
34196       point: point,
34197       lineStart: lineStart,
34198       lineEnd: lineEnd,
34199       polygonStart: function() {
34200         clip.point = pointRing;
34201         clip.lineStart = ringStart;
34202         clip.lineEnd = ringEnd;
34203         segments = [];
34204         polygon = [];
34205       },
34206       polygonEnd: function() {
34207         clip.point = point;
34208         clip.lineStart = lineStart;
34209         clip.lineEnd = lineEnd;
34210         segments = merge(segments);
34211         var startInside = polygonContains(polygon, rotatedStart);
34212         if (segments.length) {
34213           if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
34214           clipPolygon(segments, compareIntersection, startInside, interpolate, sink);
34215         } else if (startInside) {
34216           if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
34217           sink.lineStart();
34218           interpolate(null, null, 1, sink);
34219           sink.lineEnd();
34220         }
34221         if (polygonStarted) sink.polygonEnd(), polygonStarted = false;
34222         segments = polygon = null;
34223       },
34224       sphere: function() {
34225         sink.polygonStart();
34226         sink.lineStart();
34227         interpolate(null, null, 1, sink);
34228         sink.lineEnd();
34229         sink.polygonEnd();
34230       }
34231     };
34232
34233     function point(lambda, phi) {
34234       var point = rotate(lambda, phi);
34235       if (pointVisible(lambda = point[0], phi = point[1])) sink.point(lambda, phi);
34236     }
34237
34238     function pointLine(lambda, phi) {
34239       var point = rotate(lambda, phi);
34240       line.point(point[0], point[1]);
34241     }
34242
34243     function lineStart() {
34244       clip.point = pointLine;
34245       line.lineStart();
34246     }
34247
34248     function lineEnd() {
34249       clip.point = point;
34250       line.lineEnd();
34251     }
34252
34253     function pointRing(lambda, phi) {
34254       ring.push([lambda, phi]);
34255       var point = rotate(lambda, phi);
34256       ringSink.point(point[0], point[1]);
34257     }
34258
34259     function ringStart() {
34260       ringSink.lineStart();
34261       ring = [];
34262     }
34263
34264     function ringEnd() {
34265       pointRing(ring[0][0], ring[0][1]);
34266       ringSink.lineEnd();
34267
34268       var clean = ringSink.clean(),
34269           ringSegments = ringBuffer.result(),
34270           i, n = ringSegments.length, m,
34271           segment,
34272           point;
34273
34274       ring.pop();
34275       polygon.push(ring);
34276       ring = null;
34277
34278       if (!n) return;
34279
34280       // No intersections.
34281       if (clean & 1) {
34282         segment = ringSegments[0];
34283         if ((m = segment.length - 1) > 0) {
34284           if (!polygonStarted) sink.polygonStart(), polygonStarted = true;
34285           sink.lineStart();
34286           for (i = 0; i < m; ++i) sink.point((point = segment[i])[0], point[1]);
34287           sink.lineEnd();
34288         }
34289         return;
34290       }
34291
34292       // Rejoin connected segments.
34293       // TODO reuse ringBuffer.rejoin()?
34294       if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
34295
34296       segments.push(ringSegments.filter(validSegment));
34297     }
34298
34299     return clip;
34300   };
34301 };
34302
34303 function validSegment(segment) {
34304   return segment.length > 1;
34305 }
34306
34307 // Intersections are sorted along the clip edge. For both antimeridian cutting
34308 // and circle clipping, the same comparison is used.
34309 function compareIntersection(a, b) {
34310   return ((a = a.x)[0] < 0 ? a[1] - halfPi$3 - epsilon$4 : halfPi$3 - a[1])
34311        - ((b = b.x)[0] < 0 ? b[1] - halfPi$3 - epsilon$4 : halfPi$3 - b[1]);
34312 }
34313
34314 var clipAntimeridian = clip(
34315   function() { return true; },
34316   clipAntimeridianLine,
34317   clipAntimeridianInterpolate,
34318   [-pi$4, -halfPi$3]
34319 );
34320
34321 // Takes a line and cuts into visible segments. Return values: 0 - there were
34322 // intersections or the line was empty; 1 - no intersections; 2 - there were
34323 // intersections, and the first and last segments should be rejoined.
34324 function clipAntimeridianLine(stream) {
34325   var lambda0 = NaN,
34326       phi0 = NaN,
34327       sign0 = NaN,
34328       clean; // no intersections
34329
34330   return {
34331     lineStart: function() {
34332       stream.lineStart();
34333       clean = 1;
34334     },
34335     point: function(lambda1, phi1) {
34336       var sign1 = lambda1 > 0 ? pi$4 : -pi$4,
34337           delta = abs(lambda1 - lambda0);
34338       if (abs(delta - pi$4) < epsilon$4) { // line crosses a pole
34339         stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi$3 : -halfPi$3);
34340         stream.point(sign0, phi0);
34341         stream.lineEnd();
34342         stream.lineStart();
34343         stream.point(sign1, phi0);
34344         stream.point(lambda1, phi0);
34345         clean = 0;
34346       } else if (sign0 !== sign1 && delta >= pi$4) { // line crosses antimeridian
34347         if (abs(lambda0 - sign0) < epsilon$4) lambda0 -= sign0 * epsilon$4; // handle degeneracies
34348         if (abs(lambda1 - sign1) < epsilon$4) lambda1 -= sign1 * epsilon$4;
34349         phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1);
34350         stream.point(sign0, phi0);
34351         stream.lineEnd();
34352         stream.lineStart();
34353         stream.point(sign1, phi0);
34354         clean = 0;
34355       }
34356       stream.point(lambda0 = lambda1, phi0 = phi1);
34357       sign0 = sign1;
34358     },
34359     lineEnd: function() {
34360       stream.lineEnd();
34361       lambda0 = phi0 = NaN;
34362     },
34363     clean: function() {
34364       return 2 - clean; // if intersections, rejoin first and last segments
34365     }
34366   };
34367 }
34368
34369 function clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) {
34370   var cosPhi0,
34371       cosPhi1,
34372       sinLambda0Lambda1 = sin$1(lambda0 - lambda1);
34373   return abs(sinLambda0Lambda1) > epsilon$4
34374       ? atan((sin$1(phi0) * (cosPhi1 = cos$1(phi1)) * sin$1(lambda1)
34375           - sin$1(phi1) * (cosPhi0 = cos$1(phi0)) * sin$1(lambda0))
34376           / (cosPhi0 * cosPhi1 * sinLambda0Lambda1))
34377       : (phi0 + phi1) / 2;
34378 }
34379
34380 function clipAntimeridianInterpolate(from, to, direction, stream) {
34381   var phi;
34382   if (from == null) {
34383     phi = direction * halfPi$3;
34384     stream.point(-pi$4, phi);
34385     stream.point(0, phi);
34386     stream.point(pi$4, phi);
34387     stream.point(pi$4, 0);
34388     stream.point(pi$4, -phi);
34389     stream.point(0, -phi);
34390     stream.point(-pi$4, -phi);
34391     stream.point(-pi$4, 0);
34392     stream.point(-pi$4, phi);
34393   } else if (abs(from[0] - to[0]) > epsilon$4) {
34394     var lambda = from[0] < to[0] ? pi$4 : -pi$4;
34395     phi = direction * lambda / 2;
34396     stream.point(-lambda, phi);
34397     stream.point(0, phi);
34398     stream.point(lambda, phi);
34399   } else {
34400     stream.point(to[0], to[1]);
34401   }
34402 }
34403
34404 var clipCircle = function(radius, delta) {
34405   var cr = cos$1(radius),
34406       smallRadius = cr > 0,
34407       notHemisphere = abs(cr) > epsilon$4; // TODO optimise for this common case
34408
34409   function interpolate(from, to, direction, stream) {
34410     circleStream(stream, radius, delta, direction, from, to);
34411   }
34412
34413   function visible(lambda, phi) {
34414     return cos$1(lambda) * cos$1(phi) > cr;
34415   }
34416
34417   // Takes a line and cuts into visible segments. Return values used for polygon
34418   // clipping: 0 - there were intersections or the line was empty; 1 - no
34419   // intersections 2 - there were intersections, and the first and last segments
34420   // should be rejoined.
34421   function clipLine(stream) {
34422     var point0, // previous point
34423         c0, // code for previous point
34424         v0, // visibility of previous point
34425         v00, // visibility of first point
34426         clean; // no intersections
34427     return {
34428       lineStart: function() {
34429         v00 = v0 = false;
34430         clean = 1;
34431       },
34432       point: function(lambda, phi) {
34433         var point1 = [lambda, phi],
34434             point2,
34435             v = visible(lambda, phi),
34436             c = smallRadius
34437               ? v ? 0 : code(lambda, phi)
34438               : v ? code(lambda + (lambda < 0 ? pi$4 : -pi$4), phi) : 0;
34439         if (!point0 && (v00 = v0 = v)) stream.lineStart();
34440         // Handle degeneracies.
34441         // TODO ignore if not clipping polygons.
34442         if (v !== v0) {
34443           point2 = intersect(point0, point1);
34444           if (pointEqual(point0, point2) || pointEqual(point1, point2)) {
34445             point1[0] += epsilon$4;
34446             point1[1] += epsilon$4;
34447             v = visible(point1[0], point1[1]);
34448           }
34449         }
34450         if (v !== v0) {
34451           clean = 0;
34452           if (v) {
34453             // outside going in
34454             stream.lineStart();
34455             point2 = intersect(point1, point0);
34456             stream.point(point2[0], point2[1]);
34457           } else {
34458             // inside going out
34459             point2 = intersect(point0, point1);
34460             stream.point(point2[0], point2[1]);
34461             stream.lineEnd();
34462           }
34463           point0 = point2;
34464         } else if (notHemisphere && point0 && smallRadius ^ v) {
34465           var t;
34466           // If the codes for two points are different, or are both zero,
34467           // and there this segment intersects with the small circle.
34468           if (!(c & c0) && (t = intersect(point1, point0, true))) {
34469             clean = 0;
34470             if (smallRadius) {
34471               stream.lineStart();
34472               stream.point(t[0][0], t[0][1]);
34473               stream.point(t[1][0], t[1][1]);
34474               stream.lineEnd();
34475             } else {
34476               stream.point(t[1][0], t[1][1]);
34477               stream.lineEnd();
34478               stream.lineStart();
34479               stream.point(t[0][0], t[0][1]);
34480             }
34481           }
34482         }
34483         if (v && (!point0 || !pointEqual(point0, point1))) {
34484           stream.point(point1[0], point1[1]);
34485         }
34486         point0 = point1, v0 = v, c0 = c;
34487       },
34488       lineEnd: function() {
34489         if (v0) stream.lineEnd();
34490         point0 = null;
34491       },
34492       // Rejoin first and last segments if there were intersections and the first
34493       // and last points were visible.
34494       clean: function() {
34495         return clean | ((v00 && v0) << 1);
34496       }
34497     };
34498   }
34499
34500   // Intersects the great circle between a and b with the clip circle.
34501   function intersect(a, b, two) {
34502     var pa = cartesian(a),
34503         pb = cartesian(b);
34504
34505     // We have two planes, n1.p = d1 and n2.p = d2.
34506     // Find intersection line p(t) = c1 n1 + c2 n2 + t (n1 ⨯ n2).
34507     var n1 = [1, 0, 0], // normal
34508         n2 = cartesianCross(pa, pb),
34509         n2n2 = cartesianDot(n2, n2),
34510         n1n2 = n2[0], // cartesianDot(n1, n2),
34511         determinant = n2n2 - n1n2 * n1n2;
34512
34513     // Two polar points.
34514     if (!determinant) return !two && a;
34515
34516     var c1 =  cr * n2n2 / determinant,
34517         c2 = -cr * n1n2 / determinant,
34518         n1xn2 = cartesianCross(n1, n2),
34519         A = cartesianScale(n1, c1),
34520         B = cartesianScale(n2, c2);
34521     cartesianAddInPlace(A, B);
34522
34523     // Solve |p(t)|^2 = 1.
34524     var u = n1xn2,
34525         w = cartesianDot(A, u),
34526         uu = cartesianDot(u, u),
34527         t2 = w * w - uu * (cartesianDot(A, A) - 1);
34528
34529     if (t2 < 0) return;
34530
34531     var t = sqrt$1(t2),
34532         q = cartesianScale(u, (-w - t) / uu);
34533     cartesianAddInPlace(q, A);
34534     q = spherical(q);
34535
34536     if (!two) return q;
34537
34538     // Two intersection points.
34539     var lambda0 = a[0],
34540         lambda1 = b[0],
34541         phi0 = a[1],
34542         phi1 = b[1],
34543         z;
34544
34545     if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z;
34546
34547     var delta = lambda1 - lambda0,
34548         polar = abs(delta - pi$4) < epsilon$4,
34549         meridian = polar || delta < epsilon$4;
34550
34551     if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z;
34552
34553     // Check that the first point is between a and b.
34554     if (meridian
34555         ? polar
34556           ? phi0 + phi1 > 0 ^ q[1] < (abs(q[0] - lambda0) < epsilon$4 ? phi0 : phi1)
34557           : phi0 <= q[1] && q[1] <= phi1
34558         : delta > pi$4 ^ (lambda0 <= q[0] && q[0] <= lambda1)) {
34559       var q1 = cartesianScale(u, (-w + t) / uu);
34560       cartesianAddInPlace(q1, A);
34561       return [q, spherical(q1)];
34562     }
34563   }
34564
34565   // Generates a 4-bit vector representing the location of a point relative to
34566   // the small circle's bounding box.
34567   function code(lambda, phi) {
34568     var r = smallRadius ? radius : pi$4 - radius,
34569         code = 0;
34570     if (lambda < -r) code |= 1; // left
34571     else if (lambda > r) code |= 2; // right
34572     if (phi < -r) code |= 4; // below
34573     else if (phi > r) code |= 8; // above
34574     return code;
34575   }
34576
34577   return clip(visible, clipLine, interpolate, smallRadius ? [0, -radius] : [-pi$4, radius - pi$4]);
34578 };
34579
34580 var transform$1 = function(methods) {
34581   return {
34582     stream: transformer(methods)
34583   };
34584 };
34585
34586 function transformer(methods) {
34587   return function(stream) {
34588     var s = new TransformStream;
34589     for (var key in methods) s[key] = methods[key];
34590     s.stream = stream;
34591     return s;
34592   };
34593 }
34594
34595 function TransformStream() {}
34596
34597 TransformStream.prototype = {
34598   constructor: TransformStream,
34599   point: function(x, y) { this.stream.point(x, y); },
34600   sphere: function() { this.stream.sphere(); },
34601   lineStart: function() { this.stream.lineStart(); },
34602   lineEnd: function() { this.stream.lineEnd(); },
34603   polygonStart: function() { this.stream.polygonStart(); },
34604   polygonEnd: function() { this.stream.polygonEnd(); }
34605 };
34606
34607 function fitExtent(projection, extent, object) {
34608   var w = extent[1][0] - extent[0][0],
34609       h = extent[1][1] - extent[0][1],
34610       clip = projection.clipExtent && projection.clipExtent();
34611
34612   projection
34613       .scale(150)
34614       .translate([0, 0]);
34615
34616   if (clip != null) projection.clipExtent(null);
34617
34618   geoStream(object, projection.stream(boundsStream$1));
34619
34620   var b = boundsStream$1.result(),
34621       k = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])),
34622       x = +extent[0][0] + (w - k * (b[1][0] + b[0][0])) / 2,
34623       y = +extent[0][1] + (h - k * (b[1][1] + b[0][1])) / 2;
34624
34625   if (clip != null) projection.clipExtent(clip);
34626
34627   return projection
34628       .scale(k * 150)
34629       .translate([x, y]);
34630 }
34631
34632 function fitSize(projection, size, object) {
34633   return fitExtent(projection, [[0, 0], size], object);
34634 }
34635
34636 var maxDepth = 16;
34637 var cosMinDistance = cos$1(30 * radians); // cos(minimum angular distance)
34638
34639 var resample = function(project, delta2) {
34640   return +delta2 ? resample$1(project, delta2) : resampleNone(project);
34641 };
34642
34643 function resampleNone(project) {
34644   return transformer({
34645     point: function(x, y) {
34646       x = project(x, y);
34647       this.stream.point(x[0], x[1]);
34648     }
34649   });
34650 }
34651
34652 function resample$1(project, delta2) {
34653
34654   function resampleLineTo(x0, y0, lambda0, a0, b0, c0, x1, y1, lambda1, a1, b1, c1, depth, stream) {
34655     var dx = x1 - x0,
34656         dy = y1 - y0,
34657         d2 = dx * dx + dy * dy;
34658     if (d2 > 4 * delta2 && depth--) {
34659       var a = a0 + a1,
34660           b = b0 + b1,
34661           c = c0 + c1,
34662           m = sqrt$1(a * a + b * b + c * c),
34663           phi2 = asin$1(c /= m),
34664           lambda2 = abs(abs(c) - 1) < epsilon$4 || abs(lambda0 - lambda1) < epsilon$4 ? (lambda0 + lambda1) / 2 : atan2(b, a),
34665           p = project(lambda2, phi2),
34666           x2 = p[0],
34667           y2 = p[1],
34668           dx2 = x2 - x0,
34669           dy2 = y2 - y0,
34670           dz = dy * dx2 - dx * dy2;
34671       if (dz * dz / d2 > delta2 // perpendicular projected distance
34672           || abs((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 // midpoint close to an end
34673           || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) { // angular distance
34674         resampleLineTo(x0, y0, lambda0, a0, b0, c0, x2, y2, lambda2, a /= m, b /= m, c, depth, stream);
34675         stream.point(x2, y2);
34676         resampleLineTo(x2, y2, lambda2, a, b, c, x1, y1, lambda1, a1, b1, c1, depth, stream);
34677       }
34678     }
34679   }
34680   return function(stream) {
34681     var lambda00, x00, y00, a00, b00, c00, // first point
34682         lambda0, x0, y0, a0, b0, c0; // previous point
34683
34684     var resampleStream = {
34685       point: point,
34686       lineStart: lineStart,
34687       lineEnd: lineEnd,
34688       polygonStart: function() { stream.polygonStart(); resampleStream.lineStart = ringStart; },
34689       polygonEnd: function() { stream.polygonEnd(); resampleStream.lineStart = lineStart; }
34690     };
34691
34692     function point(x, y) {
34693       x = project(x, y);
34694       stream.point(x[0], x[1]);
34695     }
34696
34697     function lineStart() {
34698       x0 = NaN;
34699       resampleStream.point = linePoint;
34700       stream.lineStart();
34701     }
34702
34703     function linePoint(lambda, phi) {
34704       var c = cartesian([lambda, phi]), p = project(lambda, phi);
34705       resampleLineTo(x0, y0, lambda0, a0, b0, c0, x0 = p[0], y0 = p[1], lambda0 = lambda, a0 = c[0], b0 = c[1], c0 = c[2], maxDepth, stream);
34706       stream.point(x0, y0);
34707     }
34708
34709     function lineEnd() {
34710       resampleStream.point = point;
34711       stream.lineEnd();
34712     }
34713
34714     function ringStart() {
34715       lineStart();
34716       resampleStream.point = ringPoint;
34717       resampleStream.lineEnd = ringEnd;
34718     }
34719
34720     function ringPoint(lambda, phi) {
34721       linePoint(lambda00 = lambda, phi), x00 = x0, y00 = y0, a00 = a0, b00 = b0, c00 = c0;
34722       resampleStream.point = linePoint;
34723     }
34724
34725     function ringEnd() {
34726       resampleLineTo(x0, y0, lambda0, a0, b0, c0, x00, y00, lambda00, a00, b00, c00, maxDepth, stream);
34727       resampleStream.lineEnd = lineEnd;
34728       lineEnd();
34729     }
34730
34731     return resampleStream;
34732   };
34733 }
34734
34735 var transformRadians = transformer({
34736   point: function(x, y) {
34737     this.stream.point(x * radians, y * radians);
34738   }
34739 });
34740
34741 function projection(project) {
34742   return projectionMutator(function() { return project; })();
34743 }
34744
34745 function projectionMutator(projectAt) {
34746   var project,
34747       k = 150, // scale
34748       x = 480, y = 250, // translate
34749       dx, dy, lambda = 0, phi = 0, // center
34750       deltaLambda = 0, deltaPhi = 0, deltaGamma = 0, rotate, projectRotate, // rotate
34751       theta = null, preclip = clipAntimeridian, // clip angle
34752       x0 = null, y0, x1, y1, postclip = identity$7, // clip extent
34753       delta2 = 0.5, projectResample = resample(projectTransform, delta2), // precision
34754       cache,
34755       cacheStream;
34756
34757   function projection(point) {
34758     point = projectRotate(point[0] * radians, point[1] * radians);
34759     return [point[0] * k + dx, dy - point[1] * k];
34760   }
34761
34762   function invert(point) {
34763     point = projectRotate.invert((point[0] - dx) / k, (dy - point[1]) / k);
34764     return point && [point[0] * degrees$1, point[1] * degrees$1];
34765   }
34766
34767   function projectTransform(x, y) {
34768     return x = project(x, y), [x[0] * k + dx, dy - x[1] * k];
34769   }
34770
34771   projection.stream = function(stream) {
34772     return cache && cacheStream === stream ? cache : cache = transformRadians(preclip(rotate, projectResample(postclip(cacheStream = stream))));
34773   };
34774
34775   projection.clipAngle = function(_) {
34776     return arguments.length ? (preclip = +_ ? clipCircle(theta = _ * radians, 6 * radians) : (theta = null, clipAntimeridian), reset()) : theta * degrees$1;
34777   };
34778
34779   projection.clipExtent = function(_) {
34780     return arguments.length ? (postclip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$7) : clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]];
34781   };
34782
34783   projection.scale = function(_) {
34784     return arguments.length ? (k = +_, recenter()) : k;
34785   };
34786
34787   projection.translate = function(_) {
34788     return arguments.length ? (x = +_[0], y = +_[1], recenter()) : [x, y];
34789   };
34790
34791   projection.center = function(_) {
34792     return arguments.length ? (lambda = _[0] % 360 * radians, phi = _[1] % 360 * radians, recenter()) : [lambda * degrees$1, phi * degrees$1];
34793   };
34794
34795   projection.rotate = function(_) {
34796     return arguments.length ? (deltaLambda = _[0] % 360 * radians, deltaPhi = _[1] % 360 * radians, deltaGamma = _.length > 2 ? _[2] % 360 * radians : 0, recenter()) : [deltaLambda * degrees$1, deltaPhi * degrees$1, deltaGamma * degrees$1];
34797   };
34798
34799   projection.precision = function(_) {
34800     return arguments.length ? (projectResample = resample(projectTransform, delta2 = _ * _), reset()) : sqrt$1(delta2);
34801   };
34802
34803   projection.fitExtent = function(extent, object) {
34804     return fitExtent(projection, extent, object);
34805   };
34806
34807   projection.fitSize = function(size, object) {
34808     return fitSize(projection, size, object);
34809   };
34810
34811   function recenter() {
34812     projectRotate = compose(rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma), project);
34813     var center = project(lambda, phi);
34814     dx = x - center[0] * k;
34815     dy = y + center[1] * k;
34816     return reset();
34817   }
34818
34819   function reset() {
34820     cache = cacheStream = null;
34821     return projection;
34822   }
34823
34824   return function() {
34825     project = projectAt.apply(this, arguments);
34826     projection.invert = project.invert && invert;
34827     return recenter();
34828   };
34829 }
34830
34831 function conicProjection(projectAt) {
34832   var phi0 = 0,
34833       phi1 = pi$4 / 3,
34834       m = projectionMutator(projectAt),
34835       p = m(phi0, phi1);
34836
34837   p.parallels = function(_) {
34838     return arguments.length ? m(phi0 = _[0] * radians, phi1 = _[1] * radians) : [phi0 * degrees$1, phi1 * degrees$1];
34839   };
34840
34841   return p;
34842 }
34843
34844 function cylindricalEqualAreaRaw(phi0) {
34845   var cosPhi0 = cos$1(phi0);
34846
34847   function forward(lambda, phi) {
34848     return [lambda * cosPhi0, sin$1(phi) / cosPhi0];
34849   }
34850
34851   forward.invert = function(x, y) {
34852     return [x / cosPhi0, asin$1(y * cosPhi0)];
34853   };
34854
34855   return forward;
34856 }
34857
34858 function conicEqualAreaRaw(y0, y1) {
34859   var sy0 = sin$1(y0), n = (sy0 + sin$1(y1)) / 2;
34860
34861   // Are the parallels symmetrical around the Equator?
34862   if (abs(n) < epsilon$4) return cylindricalEqualAreaRaw(y0);
34863
34864   var c = 1 + sy0 * (2 * n - sy0), r0 = sqrt$1(c) / n;
34865
34866   function project(x, y) {
34867     var r = sqrt$1(c - 2 * n * sin$1(y)) / n;
34868     return [r * sin$1(x *= n), r0 - r * cos$1(x)];
34869   }
34870
34871   project.invert = function(x, y) {
34872     var r0y = r0 - y;
34873     return [atan2(x, abs(r0y)) / n * sign$1(r0y), asin$1((c - (x * x + r0y * r0y) * n * n) / (2 * n))];
34874   };
34875
34876   return project;
34877 }
34878
34879 var conicEqualArea = function() {
34880   return conicProjection(conicEqualAreaRaw)
34881       .scale(155.424)
34882       .center([0, 33.6442]);
34883 };
34884
34885 var albers = function() {
34886   return conicEqualArea()
34887       .parallels([29.5, 45.5])
34888       .scale(1070)
34889       .translate([480, 250])
34890       .rotate([96, 0])
34891       .center([-0.6, 38.7]);
34892 };
34893
34894 // The projections must have mutually exclusive clip regions on the sphere,
34895 // as this will avoid emitting interleaving lines and polygons.
34896 function multiplex(streams) {
34897   var n = streams.length;
34898   return {
34899     point: function(x, y) { var i = -1; while (++i < n) streams[i].point(x, y); },
34900     sphere: function() { var i = -1; while (++i < n) streams[i].sphere(); },
34901     lineStart: function() { var i = -1; while (++i < n) streams[i].lineStart(); },
34902     lineEnd: function() { var i = -1; while (++i < n) streams[i].lineEnd(); },
34903     polygonStart: function() { var i = -1; while (++i < n) streams[i].polygonStart(); },
34904     polygonEnd: function() { var i = -1; while (++i < n) streams[i].polygonEnd(); }
34905   };
34906 }
34907
34908 // A composite projection for the United States, configured by default for
34909 // 960×500. The projection also works quite well at 960×600 if you change the
34910 // scale to 1285 and adjust the translate accordingly. The set of standard
34911 // parallels for each region comes from USGS, which is published here:
34912 // http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers
34913 var albersUsa = function() {
34914   var cache,
34915       cacheStream,
34916       lower48 = albers(), lower48Point,
34917       alaska = conicEqualArea().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, // EPSG:3338
34918       hawaii = conicEqualArea().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), hawaiiPoint, // ESRI:102007
34919       point, pointStream = {point: function(x, y) { point = [x, y]; }};
34920
34921   function albersUsa(coordinates) {
34922     var x = coordinates[0], y = coordinates[1];
34923     return point = null,
34924         (lower48Point.point(x, y), point)
34925         || (alaskaPoint.point(x, y), point)
34926         || (hawaiiPoint.point(x, y), point);
34927   }
34928
34929   albersUsa.invert = function(coordinates) {
34930     var k = lower48.scale(),
34931         t = lower48.translate(),
34932         x = (coordinates[0] - t[0]) / k,
34933         y = (coordinates[1] - t[1]) / k;
34934     return (y >= 0.120 && y < 0.234 && x >= -0.425 && x < -0.214 ? alaska
34935         : y >= 0.166 && y < 0.234 && x >= -0.214 && x < -0.115 ? hawaii
34936         : lower48).invert(coordinates);
34937   };
34938
34939   albersUsa.stream = function(stream) {
34940     return cache && cacheStream === stream ? cache : cache = multiplex([lower48.stream(cacheStream = stream), alaska.stream(stream), hawaii.stream(stream)]);
34941   };
34942
34943   albersUsa.precision = function(_) {
34944     if (!arguments.length) return lower48.precision();
34945     lower48.precision(_), alaska.precision(_), hawaii.precision(_);
34946     return reset();
34947   };
34948
34949   albersUsa.scale = function(_) {
34950     if (!arguments.length) return lower48.scale();
34951     lower48.scale(_), alaska.scale(_ * 0.35), hawaii.scale(_);
34952     return albersUsa.translate(lower48.translate());
34953   };
34954
34955   albersUsa.translate = function(_) {
34956     if (!arguments.length) return lower48.translate();
34957     var k = lower48.scale(), x = +_[0], y = +_[1];
34958
34959     lower48Point = lower48
34960         .translate(_)
34961         .clipExtent([[x - 0.455 * k, y - 0.238 * k], [x + 0.455 * k, y + 0.238 * k]])
34962         .stream(pointStream);
34963
34964     alaskaPoint = alaska
34965         .translate([x - 0.307 * k, y + 0.201 * k])
34966         .clipExtent([[x - 0.425 * k + epsilon$4, y + 0.120 * k + epsilon$4], [x - 0.214 * k - epsilon$4, y + 0.234 * k - epsilon$4]])
34967         .stream(pointStream);
34968
34969     hawaiiPoint = hawaii
34970         .translate([x - 0.205 * k, y + 0.212 * k])
34971         .clipExtent([[x - 0.214 * k + epsilon$4, y + 0.166 * k + epsilon$4], [x - 0.115 * k - epsilon$4, y + 0.234 * k - epsilon$4]])
34972         .stream(pointStream);
34973
34974     return reset();
34975   };
34976
34977   albersUsa.fitExtent = function(extent, object) {
34978     return fitExtent(albersUsa, extent, object);
34979   };
34980
34981   albersUsa.fitSize = function(size, object) {
34982     return fitSize(albersUsa, size, object);
34983   };
34984
34985   function reset() {
34986     cache = cacheStream = null;
34987     return albersUsa;
34988   }
34989
34990   return albersUsa.scale(1070);
34991 };
34992
34993 function azimuthalRaw(scale) {
34994   return function(x, y) {
34995     var cx = cos$1(x),
34996         cy = cos$1(y),
34997         k = scale(cx * cy);
34998     return [
34999       k * cy * sin$1(x),
35000       k * sin$1(y)
35001     ];
35002   }
35003 }
35004
35005 function azimuthalInvert(angle) {
35006   return function(x, y) {
35007     var z = sqrt$1(x * x + y * y),
35008         c = angle(z),
35009         sc = sin$1(c),
35010         cc = cos$1(c);
35011     return [
35012       atan2(x * sc, z * cc),
35013       asin$1(z && y * sc / z)
35014     ];
35015   }
35016 }
35017
35018 var azimuthalEqualAreaRaw = azimuthalRaw(function(cxcy) {
35019   return sqrt$1(2 / (1 + cxcy));
35020 });
35021
35022 azimuthalEqualAreaRaw.invert = azimuthalInvert(function(z) {
35023   return 2 * asin$1(z / 2);
35024 });
35025
35026 var azimuthalEqualArea = function() {
35027   return projection(azimuthalEqualAreaRaw)
35028       .scale(124.75)
35029       .clipAngle(180 - 1e-3);
35030 };
35031
35032 var azimuthalEquidistantRaw = azimuthalRaw(function(c) {
35033   return (c = acos(c)) && c / sin$1(c);
35034 });
35035
35036 azimuthalEquidistantRaw.invert = azimuthalInvert(function(z) {
35037   return z;
35038 });
35039
35040 var azimuthalEquidistant = function() {
35041   return projection(azimuthalEquidistantRaw)
35042       .scale(79.4188)
35043       .clipAngle(180 - 1e-3);
35044 };
35045
35046 function mercatorRaw(lambda, phi) {
35047   return [lambda, log$1(tan((halfPi$3 + phi) / 2))];
35048 }
35049
35050 mercatorRaw.invert = function(x, y) {
35051   return [x, 2 * atan(exp(y)) - halfPi$3];
35052 };
35053
35054 var mercator = function() {
35055   return mercatorProjection(mercatorRaw)
35056       .scale(961 / tau$4);
35057 };
35058
35059 function mercatorProjection(project) {
35060   var m = projection(project),
35061       scale = m.scale,
35062       translate = m.translate,
35063       clipExtent = m.clipExtent,
35064       clipAuto;
35065
35066   m.scale = function(_) {
35067     return arguments.length ? (scale(_), clipAuto && m.clipExtent(null), m) : scale();
35068   };
35069
35070   m.translate = function(_) {
35071     return arguments.length ? (translate(_), clipAuto && m.clipExtent(null), m) : translate();
35072   };
35073
35074   m.clipExtent = function(_) {
35075     if (!arguments.length) return clipAuto ? null : clipExtent();
35076     if (clipAuto = _ == null) {
35077       var k = pi$4 * scale(),
35078           t = translate();
35079       _ = [[t[0] - k, t[1] - k], [t[0] + k, t[1] + k]];
35080     }
35081     clipExtent(_);
35082     return m;
35083   };
35084
35085   return m.clipExtent(null);
35086 }
35087
35088 function tany(y) {
35089   return tan((halfPi$3 + y) / 2);
35090 }
35091
35092 function conicConformalRaw(y0, y1) {
35093   var cy0 = cos$1(y0),
35094       n = y0 === y1 ? sin$1(y0) : log$1(cy0 / cos$1(y1)) / log$1(tany(y1) / tany(y0)),
35095       f = cy0 * pow$1(tany(y0), n) / n;
35096
35097   if (!n) return mercatorRaw;
35098
35099   function project(x, y) {
35100     if (f > 0) { if (y < -halfPi$3 + epsilon$4) y = -halfPi$3 + epsilon$4; }
35101     else { if (y > halfPi$3 - epsilon$4) y = halfPi$3 - epsilon$4; }
35102     var r = f / pow$1(tany(y), n);
35103     return [r * sin$1(n * x), f - r * cos$1(n * x)];
35104   }
35105
35106   project.invert = function(x, y) {
35107     var fy = f - y, r = sign$1(n) * sqrt$1(x * x + fy * fy);
35108     return [atan2(x, abs(fy)) / n * sign$1(fy), 2 * atan(pow$1(f / r, 1 / n)) - halfPi$3];
35109   };
35110
35111   return project;
35112 }
35113
35114 var conicConformal = function() {
35115   return conicProjection(conicConformalRaw)
35116       .scale(109.5)
35117       .parallels([30, 30]);
35118 };
35119
35120 function equirectangularRaw(lambda, phi) {
35121   return [lambda, phi];
35122 }
35123
35124 equirectangularRaw.invert = equirectangularRaw;
35125
35126 var equirectangular = function() {
35127   return projection(equirectangularRaw)
35128       .scale(152.63);
35129 };
35130
35131 function conicEquidistantRaw(y0, y1) {
35132   var cy0 = cos$1(y0),
35133       n = y0 === y1 ? sin$1(y0) : (cy0 - cos$1(y1)) / (y1 - y0),
35134       g = cy0 / n + y0;
35135
35136   if (abs(n) < epsilon$4) return equirectangularRaw;
35137
35138   function project(x, y) {
35139     var gy = g - y, nx = n * x;
35140     return [gy * sin$1(nx), g - gy * cos$1(nx)];
35141   }
35142
35143   project.invert = function(x, y) {
35144     var gy = g - y;
35145     return [atan2(x, abs(gy)) / n * sign$1(gy), g - sign$1(n) * sqrt$1(x * x + gy * gy)];
35146   };
35147
35148   return project;
35149 }
35150
35151 var conicEquidistant = function() {
35152   return conicProjection(conicEquidistantRaw)
35153       .scale(131.154)
35154       .center([0, 13.9389]);
35155 };
35156
35157 function gnomonicRaw(x, y) {
35158   var cy = cos$1(y), k = cos$1(x) * cy;
35159   return [cy * sin$1(x) / k, sin$1(y) / k];
35160 }
35161
35162 gnomonicRaw.invert = azimuthalInvert(atan);
35163
35164 var gnomonic = function() {
35165   return projection(gnomonicRaw)
35166       .scale(144.049)
35167       .clipAngle(60);
35168 };
35169
35170 function scaleTranslate(k, tx, ty) {
35171   return k === 1 && tx === 0 && ty === 0 ? identity$7 : transformer({
35172     point: function(x, y) {
35173       this.stream.point(x * k + tx, y * k + ty);
35174     }
35175   });
35176 }
35177
35178 var identity$8 = function() {
35179   var k = 1, tx = 0, ty = 0, transform = identity$7, // scale and translate
35180       x0 = null, y0, x1, y1, clip = identity$7, // clip extent
35181       cache,
35182       cacheStream,
35183       projection;
35184
35185   function reset() {
35186     cache = cacheStream = null;
35187     return projection;
35188   }
35189
35190   return projection = {
35191     stream: function(stream) {
35192       return cache && cacheStream === stream ? cache : cache = transform(clip(cacheStream = stream));
35193     },
35194     clipExtent: function(_) {
35195       return arguments.length ? (clip = _ == null ? (x0 = y0 = x1 = y1 = null, identity$7) : clipExtent(x0 = +_[0][0], y0 = +_[0][1], x1 = +_[1][0], y1 = +_[1][1]), reset()) : x0 == null ? null : [[x0, y0], [x1, y1]];
35196     },
35197     scale: function(_) {
35198       return arguments.length ? (transform = scaleTranslate(k = +_, tx, ty), reset()) : k;
35199     },
35200     translate: function(_) {
35201       return arguments.length ? (transform = scaleTranslate(k, tx = +_[0], ty = +_[1]), reset()) : [tx, ty];
35202     },
35203     fitExtent: function(extent, object) {
35204       return fitExtent(projection, extent, object);
35205     },
35206     fitSize: function(size, object) {
35207       return fitSize(projection, size, object);
35208     }
35209   };
35210 };
35211
35212 function orthographicRaw(x, y) {
35213   return [cos$1(y) * sin$1(x), sin$1(y)];
35214 }
35215
35216 orthographicRaw.invert = azimuthalInvert(asin$1);
35217
35218 var orthographic = function() {
35219   return projection(orthographicRaw)
35220       .scale(249.5)
35221       .clipAngle(90 + epsilon$4);
35222 };
35223
35224 function stereographicRaw(x, y) {
35225   var cy = cos$1(y), k = 1 + cos$1(x) * cy;
35226   return [cy * sin$1(x) / k, sin$1(y) / k];
35227 }
35228
35229 stereographicRaw.invert = azimuthalInvert(function(z) {
35230   return 2 * atan(z);
35231 });
35232
35233 var stereographic = function() {
35234   return projection(stereographicRaw)
35235       .scale(250)
35236       .clipAngle(142);
35237 };
35238
35239 function transverseMercatorRaw(lambda, phi) {
35240   return [log$1(tan((halfPi$3 + phi) / 2)), -lambda];
35241 }
35242
35243 transverseMercatorRaw.invert = function(x, y) {
35244   return [-y, 2 * atan(exp(x)) - halfPi$3];
35245 };
35246
35247 var transverseMercator = function() {
35248   var m = mercatorProjection(transverseMercatorRaw),
35249       center = m.center,
35250       rotate = m.rotate;
35251
35252   m.center = function(_) {
35253     return arguments.length ? center([-_[1], _[0]]) : (_ = center(), [_[1], -_[0]]);
35254   };
35255
35256   m.rotate = function(_) {
35257     return arguments.length ? rotate([_[0], _[1], _.length > 2 ? _[2] + 90 : 90]) : (_ = rotate(), [_[0], _[1], _[2] - 90]);
35258   };
35259
35260   return rotate([0, 0, 90])
35261       .scale(159.155);
35262 };
35263
35264
35265
35266 var index$1 = Object.freeze({
35267         version: version,
35268         bisect: bisectRight,
35269         bisectRight: bisectRight,
35270         bisectLeft: bisectLeft,
35271         ascending: ascending,
35272         bisector: bisector,
35273         descending: descending,
35274         deviation: deviation,
35275         extent: extent,
35276         histogram: histogram,
35277         thresholdFreedmanDiaconis: freedmanDiaconis,
35278         thresholdScott: scott,
35279         thresholdSturges: sturges,
35280         max: max,
35281         mean: mean,
35282         median: median,
35283         merge: merge,
35284         min: min,
35285         pairs: pairs,
35286         permute: permute,
35287         quantile: threshold,
35288         range: range,
35289         scan: scan,
35290         shuffle: shuffle,
35291         sum: sum,
35292         ticks: ticks,
35293         tickStep: tickStep,
35294         transpose: transpose,
35295         variance: variance,
35296         zip: zip,
35297         entries: entries,
35298         keys: keys,
35299         values: values,
35300         map: map$1,
35301         set: set,
35302         nest: nest,
35303         randomUniform: uniform,
35304         randomNormal: normal,
35305         randomLogNormal: logNormal,
35306         randomBates: bates,
35307         randomIrwinHall: irwinHall,
35308         randomExponential: exponential,
35309         easeLinear: linear,
35310         easeQuad: quadInOut,
35311         easeQuadIn: quadIn,
35312         easeQuadOut: quadOut,
35313         easeQuadInOut: quadInOut,
35314         easeCubic: cubicInOut,
35315         easeCubicIn: cubicIn,
35316         easeCubicOut: cubicOut,
35317         easeCubicInOut: cubicInOut,
35318         easePoly: polyInOut,
35319         easePolyIn: polyIn,
35320         easePolyOut: polyOut,
35321         easePolyInOut: polyInOut,
35322         easeSin: sinInOut,
35323         easeSinIn: sinIn,
35324         easeSinOut: sinOut,
35325         easeSinInOut: sinInOut,
35326         easeExp: expInOut,
35327         easeExpIn: expIn,
35328         easeExpOut: expOut,
35329         easeExpInOut: expInOut,
35330         easeCircle: circleInOut,
35331         easeCircleIn: circleIn,
35332         easeCircleOut: circleOut,
35333         easeCircleInOut: circleInOut,
35334         easeBounce: bounceOut,
35335         easeBounceIn: bounceIn,
35336         easeBounceOut: bounceOut,
35337         easeBounceInOut: bounceInOut,
35338         easeBack: backInOut,
35339         easeBackIn: backIn,
35340         easeBackOut: backOut,
35341         easeBackInOut: backInOut,
35342         easeElastic: elasticOut,
35343         easeElasticIn: elasticIn,
35344         easeElasticOut: elasticOut,
35345         easeElasticInOut: elasticInOut,
35346         polygonArea: d3polygonArea,
35347         polygonCentroid: d3polygonCentroid,
35348         polygonHull: d3polygonHull,
35349         polygonContains: contains,
35350         polygonLength: length$1,
35351         path: path,
35352         quadtree: quadtree,
35353         queue: queue,
35354         arc: arc,
35355         area: area,
35356         line: line,
35357         pie: pie,
35358         radialArea: radialArea,
35359         radialLine: radialLine$1,
35360         symbol: symbol,
35361         symbols: symbols,
35362         symbolCircle: circle,
35363         symbolCross: cross$1,
35364         symbolDiamond: diamond,
35365         symbolSquare: square,
35366         symbolStar: star,
35367         symbolTriangle: triangle,
35368         symbolWye: wye,
35369         curveBasisClosed: basisClosed,
35370         curveBasisOpen: basisOpen,
35371         curveBasis: basis,
35372         curveBundle: bundle,
35373         curveCardinalClosed: cardinalClosed,
35374         curveCardinalOpen: cardinalOpen,
35375         curveCardinal: cardinal,
35376         curveCatmullRomClosed: catmullRomClosed,
35377         curveCatmullRomOpen: catmullRomOpen,
35378         curveCatmullRom: catmullRom,
35379         curveLinearClosed: linearClosed,
35380         curveLinear: curveLinear,
35381         curveMonotoneX: monotoneX,
35382         curveMonotoneY: monotoneY,
35383         curveNatural: natural,
35384         curveStep: step,
35385         curveStepAfter: stepAfter,
35386         curveStepBefore: stepBefore,
35387         stack: stack,
35388         stackOffsetExpand: expand,
35389         stackOffsetNone: none,
35390         stackOffsetSilhouette: silhouette,
35391         stackOffsetWiggle: wiggle,
35392         stackOrderAscending: ascending$1,
35393         stackOrderDescending: descending$2,
35394         stackOrderInsideOut: insideOut,
35395         stackOrderNone: none$1,
35396         stackOrderReverse: reverse,
35397         color: color,
35398         rgb: rgb,
35399         hsl: hsl,
35400         lab: lab,
35401         hcl: hcl,
35402         cubehelix: cubehelix,
35403         interpolate: interpolate,
35404         interpolateArray: array$1,
35405         interpolateDate: date,
35406         interpolateNumber: interpolateNumber,
35407         interpolateObject: object,
35408         interpolateRound: interpolateRound,
35409         interpolateString: interpolateString,
35410         interpolateTransformCss: interpolateTransformCss,
35411         interpolateTransformSvg: interpolateTransformSvg,
35412         interpolateZoom: interpolateZoom,
35413         interpolateRgb: interpolateRgb,
35414         interpolateRgbBasis: rgbBasis,
35415         interpolateRgbBasisClosed: rgbBasisClosed,
35416         interpolateHsl: hsl$2,
35417         interpolateHslLong: hslLong,
35418         interpolateLab: lab$1,
35419         interpolateHcl: hcl$2,
35420         interpolateHclLong: hclLong,
35421         interpolateCubehelix: cubehelix$2,
35422         interpolateCubehelixLong: cubehelixLong,
35423         interpolateBasis: basis$2,
35424         interpolateBasisClosed: basisClosed$1,
35425         quantize: quantize,
35426         dispatch: dispatch,
35427         dsvFormat: dsv,
35428         csvParse: csvParse,
35429         csvParseRows: csvParseRows,
35430         csvFormat: csvFormat,
35431         csvFormatRows: csvFormatRows,
35432         tsvParse: tsvParse,
35433         tsvParseRows: tsvParseRows,
35434         tsvFormat: tsvFormat,
35435         tsvFormatRows: tsvFormatRows,
35436         request: request,
35437         html: html,
35438         json: json,
35439         text: text,
35440         xml: xml,
35441         csv: csv$1,
35442         tsv: tsv$1,
35443         now: now,
35444         timer: timer,
35445         timerFlush: timerFlush,
35446         timeout: timeout$1,
35447         interval: interval$1,
35448         timeInterval: newInterval,
35449         timeMillisecond: millisecond,
35450         timeMilliseconds: milliseconds,
35451         timeSecond: second,
35452         timeSeconds: seconds,
35453         timeMinute: minute,
35454         timeMinutes: minutes,
35455         timeHour: hour,
35456         timeHours: hours,
35457         timeDay: day,
35458         timeDays: days,
35459         timeWeek: sunday,
35460         timeWeeks: sundays,
35461         timeSunday: sunday,
35462         timeSundays: sundays,
35463         timeMonday: monday,
35464         timeMondays: mondays,
35465         timeTuesday: tuesday,
35466         timeTuesdays: tuesdays,
35467         timeWednesday: wednesday,
35468         timeWednesdays: wednesdays,
35469         timeThursday: thursday,
35470         timeThursdays: thursdays,
35471         timeFriday: friday,
35472         timeFridays: fridays,
35473         timeSaturday: saturday,
35474         timeSaturdays: saturdays,
35475         timeMonth: month,
35476         timeMonths: months,
35477         timeYear: year,
35478         timeYears: years,
35479         utcMillisecond: millisecond,
35480         utcMilliseconds: milliseconds,
35481         utcSecond: second,
35482         utcSeconds: seconds,
35483         utcMinute: utcMinute,
35484         utcMinutes: utcMinutes,
35485         utcHour: utcHour,
35486         utcHours: utcHours,
35487         utcDay: utcDay,
35488         utcDays: utcDays,
35489         utcWeek: utcSunday,
35490         utcWeeks: utcSundays,
35491         utcSunday: utcSunday,
35492         utcSundays: utcSundays,
35493         utcMonday: utcMonday,
35494         utcMondays: utcMondays,
35495         utcTuesday: utcTuesday,
35496         utcTuesdays: utcTuesdays,
35497         utcWednesday: utcWednesday,
35498         utcWednesdays: utcWednesdays,
35499         utcThursday: utcThursday,
35500         utcThursdays: utcThursdays,
35501         utcFriday: utcFriday,
35502         utcFridays: utcFridays,
35503         utcSaturday: utcSaturday,
35504         utcSaturdays: utcSaturdays,
35505         utcMonth: utcMonth,
35506         utcMonths: utcMonths,
35507         utcYear: utcYear,
35508         utcYears: utcYears,
35509         get format () { return format; },
35510         get formatPrefix () { return formatPrefix; },
35511         formatLocale: formatLocale,
35512         formatDefaultLocale: defaultLocale,
35513         formatSpecifier: formatSpecifier,
35514         precisionFixed: precisionFixed,
35515         precisionPrefix: precisionPrefix,
35516         precisionRound: precisionRound,
35517         get timeFormat () { return timeFormat; },
35518         get timeParse () { return timeParse; },
35519         get utcFormat () { return utcFormat; },
35520         get utcParse () { return utcParse; },
35521         isoFormat: formatIso,
35522         isoParse: parseIso,
35523         timeFormatLocale: formatLocale$1,
35524         timeFormatDefaultLocale: defaultLocale$1,
35525         scaleBand: band,
35526         scalePoint: point$4,
35527         scaleIdentity: identity$4,
35528         scaleLinear: linear$2,
35529         scaleLog: log,
35530         scaleOrdinal: ordinal,
35531         scaleImplicit: implicit,
35532         scalePow: pow,
35533         scaleSqrt: sqrt,
35534         scaleQuantile: quantile$$1,
35535         scaleQuantize: quantize$1,
35536         scaleThreshold: threshold$1,
35537         scaleTime: time,
35538         scaleUtc: utcTime,
35539         schemeCategory10: category10,
35540         schemeCategory20b: category20b,
35541         schemeCategory20c: category20c,
35542         schemeCategory20: category20,
35543         scaleSequential: sequential,
35544         interpolateCubehelixDefault: cubehelix$3,
35545         interpolateRainbow: rainbow$1,
35546         interpolateWarm: warm,
35547         interpolateCool: cool,
35548         interpolateViridis: viridis,
35549         interpolateMagma: magma,
35550         interpolateInferno: inferno,
35551         interpolatePlasma: plasma,
35552         creator: creator,
35553         customEvent: customEvent,
35554         get event () { return event; },
35555         local: local,
35556         matcher: matcher$1,
35557         mouse: mouse,
35558         namespace: namespace,
35559         namespaces: namespaces,
35560         select: select,
35561         selectAll: selectAll,
35562         selection: selection,
35563         selector: selector,
35564         selectorAll: selectorAll,
35565         touch: touch,
35566         touches: touches,
35567         window: window$1,
35568         active: active,
35569         interrupt: interrupt,
35570         transition: transition,
35571         axisTop: axisTop,
35572         axisRight: axisRight,
35573         axisBottom: axisBottom,
35574         axisLeft: axisLeft,
35575         cluster: cluster,
35576         hierarchy: hierarchy,
35577         pack: index$2,
35578         packSiblings: siblings,
35579         packEnclose: enclose,
35580         partition: partition,
35581         stratify: stratify,
35582         tree: tree,
35583         treemap: index$3,
35584         treemapBinary: binary,
35585         treemapDice: treemapDice,
35586         treemapSlice: treemapSlice,
35587         treemapSliceDice: sliceDice,
35588         treemapSquarify: squarify,
35589         treemapResquarify: resquarify,
35590         forceCenter: center$1,
35591         forceCollide: collide,
35592         forceLink: link,
35593         forceManyBody: manyBody,
35594         forceSimulation: simulation,
35595         forceX: x$3,
35596         forceY: y$3,
35597         drag: drag,
35598         dragDisable: dragDisable,
35599         dragEnable: yesdrag,
35600         voronoi: voronoi,
35601         zoom: zoom,
35602         zoomIdentity: identity$6,
35603         zoomTransform: transform,
35604         brush: brush,
35605         brushX: brushX,
35606         brushY: brushY,
35607         brushSelection: brushSelection,
35608         chord: chord,
35609         ribbon: ribbon,
35610         geoAlbers: albers,
35611         geoAlbersUsa: albersUsa,
35612         geoArea: area$1,
35613         geoAzimuthalEqualArea: azimuthalEqualArea,
35614         geoAzimuthalEqualAreaRaw: azimuthalEqualAreaRaw,
35615         geoAzimuthalEquidistant: azimuthalEquidistant,
35616         geoAzimuthalEquidistantRaw: azimuthalEquidistantRaw,
35617         geoBounds: bounds,
35618         geoCentroid: d3GeoCentroid,
35619         geoCircle: circle$1,
35620         geoClipExtent: extent$1,
35621         geoConicConformal: conicConformal,
35622         geoConicConformalRaw: conicConformalRaw,
35623         geoConicEqualArea: conicEqualArea,
35624         geoConicEqualAreaRaw: conicEqualAreaRaw,
35625         geoConicEquidistant: conicEquidistant,
35626         geoConicEquidistantRaw: conicEquidistantRaw,
35627         geoDistance: distance,
35628         geoEquirectangular: equirectangular,
35629         geoEquirectangularRaw: equirectangularRaw,
35630         geoGnomonic: gnomonic,
35631         geoGnomonicRaw: gnomonicRaw,
35632         geoGraticule: graticule,
35633         geoGraticule10: graticule10,
35634         geoIdentity: identity$8,
35635         geoInterpolate: interpolate$2,
35636         geoLength: d3GeoLength,
35637         geoMercator: mercator,
35638         geoMercatorRaw: mercatorRaw,
35639         geoOrthographic: orthographic,
35640         geoOrthographicRaw: orthographicRaw,
35641         geoPath: index$5,
35642         geoProjection: projection,
35643         geoProjectionMutator: projectionMutator,
35644         geoRotation: rotation,
35645         geoStereographic: stereographic,
35646         geoStereographicRaw: stereographicRaw,
35647         geoStream: geoStream,
35648         geoTransform: transform$1,
35649         geoTransverseMercator: transverseMercator,
35650         geoTransverseMercatorRaw: transverseMercatorRaw
35651 });
35652
35653 /*
35654     Bypasses features of D3's default projection stream pipeline that are unnecessary:
35655     * Antimeridian clipping
35656     * Spherical rotation
35657     * Resampling
35658 */
35659 function geoRawMercator() {
35660     var project = mercatorRaw,
35661         k = 512 / Math.PI, // scale
35662         x = 0, y = 0, // translate
35663         clipExtent = [[0, 0], [0, 0]];
35664
35665
35666     function projection(point) {
35667         point = project(point[0] * Math.PI / 180, point[1] * Math.PI / 180);
35668         return [point[0] * k + x, y - point[1] * k];
35669     }
35670
35671
35672     projection.invert = function(point) {
35673         point = project.invert((point[0] - x) / k, (y - point[1]) / k);
35674         return point && [point[0] * 180 / Math.PI, point[1] * 180 / Math.PI];
35675     };
35676
35677
35678     projection.scale = function(_) {
35679         if (!arguments.length) return k;
35680         k = +_;
35681         return projection;
35682     };
35683
35684
35685     projection.translate = function(_) {
35686         if (!arguments.length) return [x, y];
35687         x = +_[0];
35688         y = +_[1];
35689         return projection;
35690     };
35691
35692
35693     projection.clipExtent = function(_) {
35694         if (!arguments.length) return clipExtent;
35695         clipExtent = _;
35696         return projection;
35697     };
35698
35699
35700     projection.transform = function(_) {
35701         if (!arguments.length) return identity$6.translate(x, y).scale(k);
35702         x = +_.x;
35703         y = +_.y;
35704         k = +_.k;
35705         return projection;
35706     };
35707
35708
35709     projection.stream = transform$1({
35710         point: function(x, y) {
35711             x = projection([x, y]);
35712             this.stream.point(x[0], x[1]);
35713         }
35714     }).stream;
35715
35716
35717     return projection;
35718 }
35719
35720 function geoRoundCoords(c) {
35721     return [Math.floor(c[0]), Math.floor(c[1])];
35722 }
35723
35724
35725 function geoInterp(p1, p2, t) {
35726     return [p1[0] + (p2[0] - p1[0]) * t,
35727             p1[1] + (p2[1] - p1[1]) * t];
35728 }
35729
35730
35731 // 2D cross product of OA and OB vectors, i.e. z-component of their 3D cross product.
35732 // Returns a positive value, if OAB makes a counter-clockwise turn,
35733 // negative for clockwise turn, and zero if the points are collinear.
35734 function geoCross(o, a, b) {
35735     return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0]);
35736 }
35737
35738
35739 // http://jsperf.com/id-dist-optimization
35740 function geoEuclideanDistance(a, b) {
35741     var x = a[0] - b[0], y = a[1] - b[1];
35742     return Math.sqrt((x * x) + (y * y));
35743 }
35744
35745
35746 // using WGS84 polar radius (6356752.314245179 m)
35747 // const = 2 * PI * r / 360
35748 function geoLatToMeters(dLat) {
35749     return dLat * 110946.257617;
35750 }
35751
35752
35753 // using WGS84 equatorial radius (6378137.0 m)
35754 // const = 2 * PI * r / 360
35755 function geoLonToMeters(dLon, atLat) {
35756     return Math.abs(atLat) >= 90 ? 0 :
35757         dLon * 111319.490793 * Math.abs(Math.cos(atLat * (Math.PI/180)));
35758 }
35759
35760
35761 // using WGS84 polar radius (6356752.314245179 m)
35762 // const = 2 * PI * r / 360
35763 function geoMetersToLat(m) {
35764     return m / 110946.257617;
35765 }
35766
35767
35768 // using WGS84 equatorial radius (6378137.0 m)
35769 // const = 2 * PI * r / 360
35770 function geoMetersToLon(m, atLat) {
35771     return Math.abs(atLat) >= 90 ? 0 :
35772         m / 111319.490793 / Math.abs(Math.cos(atLat * (Math.PI/180)));
35773 }
35774
35775
35776 function geoOffsetToMeters(offset) {
35777     var equatRadius = 6356752.314245179,
35778         polarRadius = 6378137.0,
35779         tileSize = 256;
35780
35781     return [
35782         offset[0] * 2 * Math.PI * equatRadius / tileSize,
35783         -offset[1] * 2 * Math.PI * polarRadius / tileSize
35784     ];
35785 }
35786
35787
35788 function geoMetersToOffset(meters) {
35789     var equatRadius = 6356752.314245179,
35790         polarRadius = 6378137.0,
35791         tileSize = 256;
35792
35793     return [
35794         meters[0] * tileSize / (2 * Math.PI * equatRadius),
35795         -meters[1] * tileSize / (2 * Math.PI * polarRadius)
35796     ];
35797 }
35798
35799
35800 // Equirectangular approximation of spherical distances on Earth
35801 function geoSphericalDistance(a, b) {
35802     var x = geoLonToMeters(a[0] - b[0], (a[1] + b[1]) / 2),
35803         y = geoLatToMeters(a[1] - b[1]);
35804     return Math.sqrt((x * x) + (y * y));
35805 }
35806
35807
35808 function geoEdgeEqual(a, b) {
35809     return (a[0] === b[0] && a[1] === b[1]) ||
35810         (a[0] === b[1] && a[1] === b[0]);
35811 }
35812
35813
35814 // Return the counterclockwise angle in the range (-pi, pi)
35815 // between the positive X axis and the line intersecting a and b.
35816 function geoAngle(a, b, projection) {
35817     a = projection(a.loc);
35818     b = projection(b.loc);
35819     return Math.atan2(b[1] - a[1], b[0] - a[0]);
35820 }
35821
35822
35823 // Choose the edge with the minimal distance from `point` to its orthogonal
35824 // projection onto that edge, if such a projection exists, or the distance to
35825 // the closest vertex on that edge. Returns an object with the `index` of the
35826 // chosen edge, the chosen `loc` on that edge, and the `distance` to to it.
35827 function geoChooseEdge(nodes, point, projection) {
35828     var dist = geoEuclideanDistance,
35829         points = nodes.map(function(n) { return projection(n.loc); }),
35830         min = Infinity,
35831         idx, loc;
35832
35833     function dot(p, q) {
35834         return p[0] * q[0] + p[1] * q[1];
35835     }
35836
35837     for (var i = 0; i < points.length - 1; i++) {
35838         var o = points[i],
35839             s = [points[i + 1][0] - o[0],
35840                  points[i + 1][1] - o[1]],
35841             v = [point[0] - o[0],
35842                  point[1] - o[1]],
35843             proj = dot(v, s) / dot(s, s),
35844             p;
35845
35846         if (proj < 0) {
35847             p = o;
35848         } else if (proj > 1) {
35849             p = points[i + 1];
35850         } else {
35851             p = [o[0] + proj * s[0], o[1] + proj * s[1]];
35852         }
35853
35854         var d = dist(p, point);
35855         if (d < min) {
35856             min = d;
35857             idx = i + 1;
35858             loc = projection.invert(p);
35859         }
35860     }
35861
35862     return {
35863         index: idx,
35864         distance: min,
35865         loc: loc
35866     };
35867 }
35868
35869
35870 // Return the intersection point of 2 line segments.
35871 // From https://github.com/pgkelley4/line-segments-intersect
35872 // This uses the vector cross product approach described below:
35873 //  http://stackoverflow.com/a/565282/786339
35874 function geoLineIntersection(a, b) {
35875     function subtractPoints(point1, point2) {
35876         return [point1[0] - point2[0], point1[1] - point2[1]];
35877     }
35878     function crossProduct(point1, point2) {
35879         return point1[0] * point2[1] - point1[1] * point2[0];
35880     }
35881
35882     var p = [a[0][0], a[0][1]],
35883         p2 = [a[1][0], a[1][1]],
35884         q = [b[0][0], b[0][1]],
35885         q2 = [b[1][0], b[1][1]],
35886         r = subtractPoints(p2, p),
35887         s = subtractPoints(q2, q),
35888         uNumerator = crossProduct(subtractPoints(q, p), r),
35889         denominator = crossProduct(r, s);
35890
35891     if (uNumerator && denominator) {
35892         var u = uNumerator / denominator,
35893             t = crossProduct(subtractPoints(q, p), s) / denominator;
35894
35895         if ((t >= 0) && (t <= 1) && (u >= 0) && (u <= 1)) {
35896             return geoInterp(p, p2, t);
35897         }
35898     }
35899
35900     return null;
35901 }
35902
35903
35904 function geoPathIntersections(path1, path2) {
35905     var intersections = [];
35906     for (var i = 0; i < path1.length - 1; i++) {
35907         for (var j = 0; j < path2.length - 1; j++) {
35908             var a = [ path1[i], path1[i+1] ],
35909                 b = [ path2[j], path2[j+1] ],
35910                 hit = geoLineIntersection(a, b);
35911             if (hit) intersections.push(hit);
35912         }
35913     }
35914     return intersections;
35915 }
35916
35917
35918 // Return whether point is contained in polygon.
35919 //
35920 // `point` should be a 2-item array of coordinates.
35921 // `polygon` should be an array of 2-item arrays of coordinates.
35922 //
35923 // From https://github.com/substack/point-in-polygon.
35924 // ray-casting algorithm based on
35925 // http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
35926 //
35927 function geoPointInPolygon(point, polygon) {
35928     var x = point[0],
35929         y = point[1],
35930         inside = false;
35931
35932     for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
35933         var xi = polygon[i][0], yi = polygon[i][1];
35934         var xj = polygon[j][0], yj = polygon[j][1];
35935
35936         var intersect = ((yi > y) !== (yj > y)) &&
35937             (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
35938         if (intersect) inside = !inside;
35939     }
35940
35941     return inside;
35942 }
35943
35944
35945 function geoPolygonContainsPolygon(outer, inner) {
35946     return lodash.every(inner, function(point) {
35947         return geoPointInPolygon(point, outer);
35948     });
35949 }
35950
35951
35952 function geoPolygonIntersectsPolygon(outer, inner, checkSegments) {
35953     function testSegments(outer, inner) {
35954         for (var i = 0; i < outer.length - 1; i++) {
35955             for (var j = 0; j < inner.length - 1; j++) {
35956                 var a = [ outer[i], outer[i+1] ],
35957                     b = [ inner[j], inner[j+1] ];
35958                 if (geoLineIntersection(a, b)) return true;
35959             }
35960         }
35961         return false;
35962     }
35963
35964     function testPoints(outer, inner) {
35965         return lodash.some(inner, function(point) {
35966             return geoPointInPolygon(point, outer);
35967         });
35968     }
35969
35970    return testPoints(outer, inner) || (!!checkSegments && testSegments(outer, inner));
35971 }
35972
35973
35974 function geoPathLength(path) {
35975     var length = 0;
35976     for (var i = 0; i < path.length - 1; i++) {
35977         length += geoEuclideanDistance(path[i], path[i + 1]);
35978     }
35979     return length;
35980 }
35981
35982 function osmNode() {
35983     if (!(this instanceof osmNode)) {
35984         return (new osmNode()).initialize(arguments);
35985     } else if (arguments.length) {
35986         this.initialize(arguments);
35987     }
35988 }
35989
35990 osmEntity$$1.node = osmNode;
35991
35992 osmNode.prototype = Object.create(osmEntity$$1.prototype);
35993
35994 lodash.extend(osmNode.prototype, {
35995
35996     type: 'node',
35997
35998
35999     extent: function() {
36000         return new geoExtent$$1(this.loc);
36001     },
36002
36003
36004     geometry: function(graph) {
36005         return graph.transient(this, 'geometry', function() {
36006             return graph.isPoi(this) ? 'point' : 'vertex';
36007         });
36008     },
36009
36010
36011     move: function(loc) {
36012         return this.update({loc: loc});
36013     },
36014
36015
36016     isIntersection: function(resolver) {
36017         return resolver.transient(this, 'isIntersection', function() {
36018             return resolver.parentWays(this).filter(function(parent) {
36019                 return (parent.tags.highway ||
36020                     parent.tags.waterway ||
36021                     parent.tags.railway ||
36022                     parent.tags.aeroway) &&
36023                     parent.geometry(resolver) === 'line';
36024             }).length > 1;
36025         });
36026     },
36027
36028
36029     isHighwayIntersection: function(resolver) {
36030         return resolver.transient(this, 'isHighwayIntersection', function() {
36031             return resolver.parentWays(this).filter(function(parent) {
36032                 return parent.tags.highway && parent.geometry(resolver) === 'line';
36033             }).length > 1;
36034         });
36035     },
36036
36037
36038     isOnAddressLine: function(resolver) {
36039         return resolver.transient(this, 'isOnAddressLine', function() {
36040             return resolver.parentWays(this).filter(function(parent) {
36041                 return parent.tags.hasOwnProperty('addr:interpolation') &&
36042                     parent.geometry(resolver) === 'line';
36043             }).length > 0;
36044         });
36045     },
36046
36047
36048     asJXON: function(changeset_id) {
36049         var r = {
36050             node: {
36051                 '@id': this.osmId(),
36052                 '@lon': this.loc[0],
36053                 '@lat': this.loc[1],
36054                 '@version': (this.version || 0),
36055                 tag: lodash.map(this.tags, function(v, k) {
36056                     return { keyAttributes: { k: k, v: v } };
36057                 })
36058             }
36059         };
36060         if (changeset_id) r.node['@changeset'] = changeset_id;
36061         return r;
36062     },
36063
36064
36065     asGeoJSON: function() {
36066         return {
36067             type: 'Point',
36068             coordinates: this.loc
36069         };
36070     }
36071 });
36072
36073 /*
36074   Order the nodes of a way in reverse order and reverse any direction dependent tags
36075   other than `oneway`. (We assume that correcting a backwards oneway is the primary
36076   reason for reversing a way.)
36077
36078   The following transforms are performed:
36079
36080     Keys:
36081           *:right=* ⟺ *:left=*
36082         *:forward=* ⟺ *:backward=*
36083        direction=up ⟺ direction=down
36084          incline=up ⟺ incline=down
36085             *=right ⟺ *=left
36086
36087     Relation members:
36088        role=forward ⟺ role=backward
36089          role=north ⟺ role=south
36090           role=east ⟺ role=west
36091
36092    In addition, numeric-valued `incline` tags are negated.
36093
36094    The JOSM implementation was used as a guide, but transformations that were of unclear benefit
36095    or adjusted tags that don't seem to be used in practice were omitted.
36096
36097    Also, each node on the way is examined for its own tags and the following transformations are performed
36098    in order to ensure associated nodes (eg a Stop Sign) is also reversed
36099
36100     Node Keys:
36101         direction=forward ⟺ direction=backward
36102         direction=left ⟺ direction=right
36103         *:forward=* ⟺ *:backward=*
36104         *:left=* ⟺ *:right=*
36105
36106    References:
36107       http://wiki.openstreetmap.org/wiki/Forward_%26_backward,_left_%26_right
36108       http://wiki.openstreetmap.org/wiki/Key:direction#Steps
36109       http://wiki.openstreetmap.org/wiki/Key:incline
36110       http://wiki.openstreetmap.org/wiki/Route#Members
36111       http://josm.openstreetmap.de/browser/josm/trunk/src/org/openstreetmap/josm/corrector/ReverseWayTagCorrector.java
36112       http://wiki.openstreetmap.org/wiki/Tag:highway%3Dstop
36113       http://wiki.openstreetmap.org/wiki/Key:traffic_sign#On_a_way_or_area
36114  */
36115 function actionReverse(wayId, options) {
36116     var replacements = [
36117             [/:right$/, ':left'], [/:left$/, ':right'],
36118             [/:forward$/, ':backward'], [/:backward$/, ':forward']
36119         ],
36120         numeric = /^([+\-]?)(?=[\d.])/,
36121         roleReversals = {
36122             forward: 'backward',
36123             backward: 'forward',
36124             north: 'south',
36125             south: 'north',
36126             east: 'west',
36127             west: 'east'
36128         };
36129
36130
36131     function reverseKey(key) {
36132         for (var i = 0; i < replacements.length; ++i) {
36133             var replacement = replacements[i];
36134             if (replacement[0].test(key)) {
36135                 return key.replace(replacement[0], replacement[1]);
36136             }
36137         }
36138         return key;
36139     }
36140
36141
36142     function reverseValue(key, value) {
36143         if (key === 'incline' && numeric.test(value)) {
36144             return value.replace(numeric, function(_, sign) { return sign === '-' ? '' : '-'; });
36145         } else if (key === 'incline' || key === 'direction') {
36146             return {up: 'down', down: 'up'}[value] || value;
36147         } else if (options && options.reverseOneway && key === 'oneway') {
36148             return {yes: '-1', '1': '-1', '-1': 'yes'}[value] || value;
36149         } else {
36150             return {left: 'right', right: 'left'}[value] || value;
36151         }
36152     }
36153
36154
36155     function reverseDirectionTags(node) {
36156         // Update the direction based tags as appropriate then return an updated node
36157         return node.update({tags: lodash.transform(node.tags, function(acc, tagValue, tagKey) {
36158             // See if this is a direction tag and reverse (or use existing value if not recognised)
36159             if (tagKey === 'direction') {
36160                 acc[tagKey] = {forward: 'backward', backward: 'forward', left: 'right', right: 'left'}[tagValue] || tagValue;
36161             } else {
36162                 // Use the reverseKey method to cater for situations such as traffic_sign:forward=stop
36163                 // This will pass through other tags unchanged
36164                 acc[reverseKey(tagKey)] = tagValue;
36165             }
36166             return acc;
36167         }, {})});
36168     }
36169
36170
36171     function reverseTagsOnNodes(graph, nodeIds) {
36172         // Reverse the direction of appropriate tags attached to the nodes (#3076)
36173         return lodash(nodeIds)
36174             // Get each node from the graph
36175             .map(function(nodeId) { return graph.entity(nodeId);})
36176             // Check tags on the node, if there aren't any, we can skip
36177             .filter(function(existingNode) { return existingNode.tags !== undefined;})
36178             // Get a new version of each node with the appropriate tags reversed
36179             .map(function(existingNode) { return reverseDirectionTags(existingNode);})
36180             // Chain together consecutive updates to the graph for each updated node and return
36181             .reduce(function (accGraph, value) { return accGraph.replace(value); }, graph);
36182     }
36183
36184
36185     return function(graph) {
36186         var way = graph.entity(wayId),
36187             nodes = way.nodes.slice().reverse(),
36188             tags = {}, key, role;
36189
36190         for (key in way.tags) {
36191             tags[reverseKey(key)] = reverseValue(key, way.tags[key]);
36192         }
36193
36194         graph.parentRelations(way).forEach(function(relation) {
36195             relation.members.forEach(function(member, index) {
36196                 if (member.id === way.id && (role = roleReversals[member.role])) {
36197                     relation = relation.updateMember({role: role}, index);
36198                     graph = graph.replace(relation);
36199                 }
36200             });
36201         });
36202
36203         // Reverse any associated directions on nodes on the way and then replace
36204         // the way itself with the reversed node ids and updated way tags
36205         return reverseTagsOnNodes(graph, nodes).replace(way.update({nodes: nodes, tags: tags}));
36206     };
36207 }
36208
36209 // For fixing up rendering of multipolygons with tags on the outer member.
36210 // https://github.com/openstreetmap/iD/issues/613
36211 function osmIsSimpleMultipolygonOuterMember(entity, graph) {
36212     if (entity.type !== 'way')
36213         return false;
36214
36215     var parents = graph.parentRelations(entity);
36216     if (parents.length !== 1)
36217         return false;
36218
36219     var parent = parents[0];
36220     if (!parent.isMultipolygon() || Object.keys(parent.tags).length > 1)
36221         return false;
36222
36223     var members = parent.members, member;
36224     for (var i = 0; i < members.length; i++) {
36225         member = members[i];
36226         if (member.id === entity.id && member.role && member.role !== 'outer')
36227             return false; // Not outer member
36228         if (member.id !== entity.id && (!member.role || member.role === 'outer'))
36229             return false; // Not a simple multipolygon
36230     }
36231
36232     return parent;
36233 }
36234
36235
36236 function osmSimpleMultipolygonOuterMember(entity, graph) {
36237     if (entity.type !== 'way')
36238         return false;
36239
36240     var parents = graph.parentRelations(entity);
36241     if (parents.length !== 1)
36242         return false;
36243
36244     var parent = parents[0];
36245     if (!parent.isMultipolygon() || Object.keys(parent.tags).length > 1)
36246         return false;
36247
36248     var members = parent.members, member, outerMember;
36249     for (var i = 0; i < members.length; i++) {
36250         member = members[i];
36251         if (!member.role || member.role === 'outer') {
36252             if (outerMember)
36253                 return false; // Not a simple multipolygon
36254             outerMember = member;
36255         }
36256     }
36257
36258     return outerMember && graph.hasEntity(outerMember.id);
36259 }
36260
36261
36262 // Join `array` into sequences of connecting ways.
36263 //
36264 // Segments which share identical start/end nodes will, as much as possible,
36265 // be connected with each other.
36266 //
36267 // The return value is a nested array. Each constituent array contains elements
36268 // of `array` which have been determined to connect. Each consitituent array
36269 // also has a `nodes` property whose value is an ordered array of member nodes,
36270 // with appropriate order reversal and start/end coordinate de-duplication.
36271 //
36272 // Members of `array` must have, at minimum, `type` and `id` properties.
36273 // Thus either an array of `osmWay`s or a relation member array may be
36274 // used.
36275 //
36276 // If an member has a `tags` property, its tags will be reversed via
36277 // `actionReverse` in the output.
36278 //
36279 // Incomplete members (those for which `graph.hasEntity(element.id)` returns
36280 // false) and non-way members are ignored.
36281 //
36282 function osmJoinWays(array, graph) {
36283     var joined = [], member, current, nodes, first, last, i, how, what;
36284
36285     array = array.filter(function(member) {
36286         return member.type === 'way' && graph.hasEntity(member.id);
36287     });
36288
36289     function resolve(member) {
36290         return graph.childNodes(graph.entity(member.id));
36291     }
36292
36293     function reverse(member) {
36294         return member.tags ? actionReverse(member.id, { reverseOneway: true })(graph).entity(member.id) : member;
36295     }
36296
36297     while (array.length) {
36298         member = array.shift();
36299         current = [member];
36300         current.nodes = nodes = resolve(member).slice();
36301         joined.push(current);
36302
36303         while (array.length && lodash.first(nodes) !== lodash.last(nodes)) {
36304             first = lodash.first(nodes);
36305             last  = lodash.last(nodes);
36306
36307             for (i = 0; i < array.length; i++) {
36308                 member = array[i];
36309                 what = resolve(member);
36310
36311                 if (last === lodash.first(what)) {
36312                     how  = nodes.push;
36313                     what = what.slice(1);
36314                     break;
36315                 } else if (last === lodash.last(what)) {
36316                     how  = nodes.push;
36317                     what = what.slice(0, -1).reverse();
36318                     member = reverse(member);
36319                     break;
36320                 } else if (first === lodash.last(what)) {
36321                     how  = nodes.unshift;
36322                     what = what.slice(0, -1);
36323                     break;
36324                 } else if (first === lodash.first(what)) {
36325                     how  = nodes.unshift;
36326                     what = what.slice(1).reverse();
36327                     member = reverse(member);
36328                     break;
36329                 } else {
36330                     what = how = null;
36331                 }
36332             }
36333
36334             if (!what)
36335                 break; // No more joinable ways.
36336
36337             how.apply(current, [member]);
36338             how.apply(nodes, what);
36339
36340             array.splice(i, 1);
36341         }
36342     }
36343
36344     return joined;
36345 }
36346
36347 function osmRelation() {
36348     if (!(this instanceof osmRelation)) {
36349         return (new osmRelation()).initialize(arguments);
36350     } else if (arguments.length) {
36351         this.initialize(arguments);
36352     }
36353 }
36354
36355
36356 osmEntity$$1.relation = osmRelation;
36357
36358 osmRelation.prototype = Object.create(osmEntity$$1.prototype);
36359
36360
36361 osmRelation.creationOrder = function(a, b) {
36362     var aId = parseInt(osmEntity$$1.id.toOSM(a.id), 10);
36363     var bId = parseInt(osmEntity$$1.id.toOSM(b.id), 10);
36364
36365     if (aId < 0 || bId < 0) return aId - bId;
36366     return bId - aId;
36367 };
36368
36369
36370 lodash.extend(osmRelation.prototype, {
36371     type: 'relation',
36372     members: [],
36373
36374
36375     copy: function(resolver, copies) {
36376         if (copies[this.id])
36377             return copies[this.id];
36378
36379         var copy = osmEntity$$1.prototype.copy.call(this, resolver, copies);
36380
36381         var members = this.members.map(function(member) {
36382             return lodash.extend({}, member, { id: resolver.entity(member.id).copy(resolver, copies).id });
36383         });
36384
36385         copy = copy.update({members: members});
36386         copies[this.id] = copy;
36387
36388         return copy;
36389     },
36390
36391
36392     extent: function(resolver, memo) {
36393         return resolver.transient(this, 'extent', function() {
36394             if (memo && memo[this.id]) return geoExtent$$1();
36395             memo = memo || {};
36396             memo[this.id] = true;
36397
36398             var extent$$1 = geoExtent$$1();
36399             for (var i = 0; i < this.members.length; i++) {
36400                 var member = resolver.hasEntity(this.members[i].id);
36401                 if (member) {
36402                     extent$$1._extend(member.extent(resolver, memo));
36403                 }
36404             }
36405             return extent$$1;
36406         });
36407     },
36408
36409
36410     geometry: function(graph) {
36411         return graph.transient(this, 'geometry', function() {
36412             return this.isMultipolygon() ? 'area' : 'relation';
36413         });
36414     },
36415
36416
36417     isDegenerate: function() {
36418         return this.members.length === 0;
36419     },
36420
36421
36422     // Return an array of members, each extended with an 'index' property whose value
36423     // is the member index.
36424     indexedMembers: function() {
36425         var result = new Array(this.members.length);
36426         for (var i = 0; i < this.members.length; i++) {
36427             result[i] = lodash.extend({}, this.members[i], {index: i});
36428         }
36429         return result;
36430     },
36431
36432
36433     // Return the first member with the given role. A copy of the member object
36434     // is returned, extended with an 'index' property whose value is the member index.
36435     memberByRole: function(role) {
36436         for (var i = 0; i < this.members.length; i++) {
36437             if (this.members[i].role === role) {
36438                 return lodash.extend({}, this.members[i], {index: i});
36439             }
36440         }
36441     },
36442
36443
36444     // Return the first member with the given id. A copy of the member object
36445     // is returned, extended with an 'index' property whose value is the member index.
36446     memberById: function(id) {
36447         for (var i = 0; i < this.members.length; i++) {
36448             if (this.members[i].id === id) {
36449                 return lodash.extend({}, this.members[i], {index: i});
36450             }
36451         }
36452     },
36453
36454
36455     // Return the first member with the given id and role. A copy of the member object
36456     // is returned, extended with an 'index' property whose value is the member index.
36457     memberByIdAndRole: function(id, role) {
36458         for (var i = 0; i < this.members.length; i++) {
36459             if (this.members[i].id === id && this.members[i].role === role) {
36460                 return lodash.extend({}, this.members[i], {index: i});
36461             }
36462         }
36463     },
36464
36465
36466     addMember: function(member, index) {
36467         var members = this.members.slice();
36468         members.splice(index === undefined ? members.length : index, 0, member);
36469         return this.update({members: members});
36470     },
36471
36472
36473     updateMember: function(member, index) {
36474         var members = this.members.slice();
36475         members.splice(index, 1, lodash.extend({}, members[index], member));
36476         return this.update({members: members});
36477     },
36478
36479
36480     removeMember: function(index) {
36481         var members = this.members.slice();
36482         members.splice(index, 1);
36483         return this.update({members: members});
36484     },
36485
36486
36487     removeMembersWithID: function(id) {
36488         var members = lodash.reject(this.members, function(m) { return m.id === id; });
36489         return this.update({members: members});
36490     },
36491
36492
36493     // Wherever a member appears with id `needle.id`, replace it with a member
36494     // with id `replacement.id`, type `replacement.type`, and the original role,
36495     // unless a member already exists with that id and role. Return an updated
36496     // relation.
36497     replaceMember: function(needle, replacement) {
36498         if (!this.memberById(needle.id))
36499             return this;
36500
36501         var members = [];
36502
36503         for (var i = 0; i < this.members.length; i++) {
36504             var member = this.members[i];
36505             if (member.id !== needle.id) {
36506                 members.push(member);
36507             } else if (!this.memberByIdAndRole(replacement.id, member.role)) {
36508                 members.push({id: replacement.id, type: replacement.type, role: member.role});
36509             }
36510         }
36511
36512         return this.update({members: members});
36513     },
36514
36515
36516     asJXON: function(changeset_id) {
36517         var r = {
36518             relation: {
36519                 '@id': this.osmId(),
36520                 '@version': this.version || 0,
36521                 member: lodash.map(this.members, function(member) {
36522                     return {
36523                         keyAttributes: {
36524                             type: member.type,
36525                             role: member.role,
36526                             ref: osmEntity$$1.id.toOSM(member.id)
36527                         }
36528                     };
36529                 }),
36530                 tag: lodash.map(this.tags, function(v, k) {
36531                     return { keyAttributes: { k: k, v: v } };
36532                 })
36533             }
36534         };
36535         if (changeset_id) r.relation['@changeset'] = changeset_id;
36536         return r;
36537     },
36538
36539
36540     asGeoJSON: function(resolver) {
36541         return resolver.transient(this, 'GeoJSON', function () {
36542             if (this.isMultipolygon()) {
36543                 return {
36544                     type: 'MultiPolygon',
36545                     coordinates: this.multipolygon(resolver)
36546                 };
36547             } else {
36548                 return {
36549                     type: 'FeatureCollection',
36550                     properties: this.tags,
36551                     features: this.members.map(function (member) {
36552                         return lodash.extend({role: member.role}, resolver.entity(member.id).asGeoJSON(resolver));
36553                     })
36554                 };
36555             }
36556         });
36557     },
36558
36559
36560     area: function(resolver) {
36561         return resolver.transient(this, 'area', function() {
36562             return area$1(this.asGeoJSON(resolver));
36563         });
36564     },
36565
36566
36567     isMultipolygon: function() {
36568         return this.tags.type === 'multipolygon';
36569     },
36570
36571
36572     isComplete: function(resolver) {
36573         for (var i = 0; i < this.members.length; i++) {
36574             if (!resolver.hasEntity(this.members[i].id)) {
36575                 return false;
36576             }
36577         }
36578         return true;
36579     },
36580
36581
36582     isRestriction: function() {
36583         return !!(this.tags.type && this.tags.type.match(/^restriction:?/));
36584     },
36585
36586
36587     // Returns an array [A0, ... An], each Ai being an array of node arrays [Nds0, ... Ndsm],
36588     // where Nds0 is an outer ring and subsequent Ndsi's (if any i > 0) being inner rings.
36589     //
36590     // This corresponds to the structure needed for rendering a multipolygon path using a
36591     // `evenodd` fill rule, as well as the structure of a GeoJSON MultiPolygon geometry.
36592     //
36593     // In the case of invalid geometries, this function will still return a result which
36594     // includes the nodes of all way members, but some Nds may be unclosed and some inner
36595     // rings not matched with the intended outer ring.
36596     //
36597     multipolygon: function(resolver) {
36598         var outers = this.members.filter(function(m) { return 'outer' === (m.role || 'outer'); }),
36599             inners = this.members.filter(function(m) { return 'inner' === m.role; });
36600
36601         outers = osmJoinWays(outers, resolver);
36602         inners = osmJoinWays(inners, resolver);
36603
36604         outers = outers.map(function(outer) { return lodash.map(outer.nodes, 'loc'); });
36605         inners = inners.map(function(inner) { return lodash.map(inner.nodes, 'loc'); });
36606
36607         var result = outers.map(function(o) {
36608             // Heuristic for detecting counterclockwise winding order. Assumes
36609             // that OpenStreetMap polygons are not hemisphere-spanning.
36610             return [area$1({ type: 'Polygon', coordinates: [o] }) > 2 * Math.PI ? o.reverse() : o];
36611         });
36612
36613         function findOuter(inner) {
36614             var o, outer;
36615
36616             for (o = 0; o < outers.length; o++) {
36617                 outer = outers[o];
36618                 if (geoPolygonContainsPolygon(outer, inner))
36619                     return o;
36620             }
36621
36622             for (o = 0; o < outers.length; o++) {
36623                 outer = outers[o];
36624                 if (geoPolygonIntersectsPolygon(outer, inner, false))
36625                     return o;
36626             }
36627         }
36628
36629         for (var i = 0; i < inners.length; i++) {
36630             var inner = inners[i];
36631
36632             if (area$1({ type: 'Polygon', coordinates: [inner] }) < 2 * Math.PI) {
36633                 inner = inner.reverse();
36634             }
36635
36636             var o = findOuter(inners[i]);
36637             if (o !== undefined)
36638                 result[o].push(inners[i]);
36639             else
36640                 result.push([inners[i]]); // Invalid geometry
36641         }
36642
36643         return result;
36644     }
36645 });
36646
36647 function osmLanes(entity) {
36648     if (entity.type !== 'way') return null;
36649     if (!entity.tags.highway) return null;
36650
36651     var tags = entity.tags;
36652     var isOneWay = entity.isOneWay();
36653     var laneCount = getLaneCount(tags, isOneWay);
36654     var maxspeed = parseMaxspeed(tags);
36655
36656     var laneDirections = parseLaneDirections(tags, isOneWay, laneCount);
36657     var forward = laneDirections.forward;
36658     var backward = laneDirections.backward;
36659     var bothways = laneDirections.bothways;
36660
36661     // parse the piped string 'x|y|z' format
36662     var turnLanes = {};
36663     turnLanes.unspecified = parseTurnLanes(tags['turn:lanes']);
36664     turnLanes.forward = parseTurnLanes(tags['turn:lanes:forward']);
36665     turnLanes.backward = parseTurnLanes(tags['turn:lanes:backward']);
36666
36667     var maxspeedLanes = {};
36668     maxspeedLanes.unspecified = parseMaxspeedLanes(tags['maxspeed:lanes'], maxspeed);
36669     maxspeedLanes.forward = parseMaxspeedLanes(tags['maxspeed:lanes:forward'], maxspeed);
36670     maxspeedLanes.backward = parseMaxspeedLanes(tags['maxspeed:lanes:backward'], maxspeed);
36671
36672     var psvLanes = {};
36673     psvLanes.unspecified = parseMiscLanes(tags['psv:lanes']);
36674     psvLanes.forward = parseMiscLanes(tags['psv:lanes:forward']);
36675     psvLanes.backward = parseMiscLanes(tags['psv:lanes:backward']);
36676
36677     var busLanes = {};
36678     busLanes.unspecified = parseMiscLanes(tags['bus:lanes']);
36679     busLanes.forward = parseMiscLanes(tags['bus:lanes:forward']);
36680     busLanes.backward = parseMiscLanes(tags['bus:lanes:backward']);
36681
36682     var taxiLanes = {};
36683     taxiLanes.unspecified = parseMiscLanes(tags['taxi:lanes']);
36684     taxiLanes.forward = parseMiscLanes(tags['taxi:lanes:forward']);
36685     taxiLanes.backward = parseMiscLanes(tags['taxi:lanes:backward']);
36686
36687     var hovLanes = {};
36688     hovLanes.unspecified = parseMiscLanes(tags['hov:lanes']);
36689     hovLanes.forward = parseMiscLanes(tags['hov:lanes:forward']);
36690     hovLanes.backward = parseMiscLanes(tags['hov:lanes:backward']);
36691
36692     var hgvLanes = {};
36693     hgvLanes.unspecified = parseMiscLanes(tags['hgv:lanes']);
36694     hgvLanes.forward = parseMiscLanes(tags['hgv:lanes:forward']);
36695     hgvLanes.backward = parseMiscLanes(tags['hgv:lanes:backward']);
36696
36697     var bicyclewayLanes = {};
36698     bicyclewayLanes.unspecified = parseBicycleWay(tags['bicycleway:lanes']);
36699     bicyclewayLanes.forward = parseBicycleWay(tags['bicycleway:lanes:forward']);
36700     bicyclewayLanes.backward = parseBicycleWay(tags['bicycleway:lanes:backward']);
36701
36702     var lanesObj = {
36703         forward: [],
36704         backward: [],
36705         unspecified: []
36706     };
36707
36708     // map forward/backward/unspecified of each lane type to lanesObj
36709     mapToLanesObj(lanesObj, turnLanes, 'turnLane');
36710     mapToLanesObj(lanesObj, maxspeedLanes, 'maxspeed');
36711     mapToLanesObj(lanesObj, psvLanes, 'psv');
36712     mapToLanesObj(lanesObj, busLanes, 'bus');
36713     mapToLanesObj(lanesObj, taxiLanes, 'taxi');
36714     mapToLanesObj(lanesObj, hovLanes, 'hov');
36715     mapToLanesObj(lanesObj, hgvLanes, 'hgv');
36716     mapToLanesObj(lanesObj, bicyclewayLanes, 'bicycleway');
36717
36718     return {
36719         metadata: {
36720             count: laneCount,
36721             oneway: isOneWay,
36722             forward: forward,
36723             backward: backward,
36724             bothways: bothways,
36725             turnLanes: turnLanes,
36726             maxspeed: maxspeed,
36727             maxspeedLanes: maxspeedLanes,
36728             psvLanes: psvLanes,
36729             busLanes: busLanes,
36730             taxiLanes: taxiLanes,
36731             hovLanes: hovLanes,
36732             hgvLanes: hgvLanes,
36733             bicyclewayLanes: bicyclewayLanes
36734         },
36735         lanes: lanesObj
36736     };
36737 }
36738
36739
36740 function getLaneCount(tags, isOneWay) {
36741     var count;
36742     if (tags.lanes) {
36743         count = parseInt(tags.lanes, 10);
36744         if (count > 0) {
36745             return count;
36746         }
36747     }
36748
36749
36750     switch (tags.highway) {
36751         case 'trunk':
36752         case 'motorway':
36753             count = isOneWay ? 2 : 4;
36754             break;
36755         default:
36756             count = isOneWay ? 1 : 2;
36757             break;
36758     }
36759
36760     return count;
36761 }
36762
36763
36764 function parseMaxspeed(tags) {
36765     var maxspeed = tags.maxspeed;
36766     if (lodash.isNumber(maxspeed)) return maxspeed;
36767     if (lodash.isString(maxspeed)) {
36768         maxspeed = maxspeed.match(/^([0-9][\.0-9]+?)(?:[ ]?(?:km\/h|kmh|kph|mph|knots))?$/g);
36769         if (!maxspeed) return;
36770         return parseInt(maxspeed, 10);
36771     }
36772 }
36773
36774
36775 function parseLaneDirections(tags, isOneWay, laneCount) {
36776     var forward = parseInt(tags['lanes:forward'], 10);
36777     var backward = parseInt(tags['lanes:backward'], 10);
36778     var bothways = parseInt(tags['lanes:both_ways'], 10) > 0 ? 1 : 0;
36779
36780     if (parseInt(tags.oneway, 10) === -1) {
36781         forward = 0;
36782         bothways = 0;
36783         backward = laneCount;
36784     }
36785     else if (isOneWay) {
36786         forward = laneCount;
36787         bothways = 0;
36788         backward = 0;
36789     }
36790     else if (lodash.isNaN(forward) && lodash.isNaN(backward)) {
36791         backward = Math.floor((laneCount - bothways) / 2);
36792         forward = laneCount - bothways - backward;
36793     }
36794     else if (lodash.isNaN(forward)) {
36795         if (backward > laneCount - bothways) {
36796             backward = laneCount - bothways;
36797         }
36798         forward = laneCount - bothways - backward;
36799     }
36800     else if (lodash.isNaN(backward)) {
36801         if (forward > laneCount - bothways) {
36802             forward = laneCount - bothways;
36803         }
36804         backward = laneCount - bothways - forward;
36805     }
36806     return {
36807         forward: forward,
36808         backward: backward,
36809         bothways: bothways
36810     };
36811 }
36812
36813
36814 function parseTurnLanes(tag){
36815     if (!tag) return;
36816
36817     var validValues = [
36818         'left', 'slight_left', 'sharp_left', 'through', 'right', 'slight_right',
36819         'sharp_right', 'reverse', 'merge_to_left', 'merge_to_right', 'none'
36820     ];
36821
36822     return tag.split('|')
36823         .map(function (s) {
36824             if (s === '') s = 'none';
36825             return s.split(';')
36826                 .map(function (d) {
36827                     return validValues.indexOf(d) === -1 ? 'unknown': d;
36828                 });
36829         });
36830 }
36831
36832
36833 function parseMaxspeedLanes(tag, maxspeed) {
36834     if (!tag) return;
36835
36836     return tag.split('|')
36837         .map(function (s) {
36838             if (s === 'none') return s;
36839             var m = parseInt(s, 10);
36840             if (s === '' || m === maxspeed) return null;
36841             return lodash.isNaN(m) ? 'unknown': m;
36842         });
36843 }
36844
36845
36846 function parseMiscLanes(tag) {
36847     if (!tag) return;
36848
36849     var validValues = [
36850         'yes', 'no', 'designated'
36851     ];
36852
36853     return tag.split('|')
36854         .map(function (s) {
36855             if (s === '') s = 'no';
36856             return validValues.indexOf(s) === -1 ? 'unknown': s;
36857         });
36858 }
36859
36860
36861 function parseBicycleWay(tag) {
36862     if (!tag) return;
36863
36864     var validValues = [
36865         'yes', 'no', 'designated', 'lane'
36866     ];
36867
36868     return tag.split('|')
36869         .map(function (s) {
36870             if (s === '') s = 'no';
36871             return validValues.indexOf(s) === -1 ? 'unknown': s;
36872         });
36873 }
36874
36875
36876 function mapToLanesObj(lanesObj, data, key) {
36877     if (data.forward) data.forward.forEach(function(l, i) {
36878         if (!lanesObj.forward[i]) lanesObj.forward[i] = {};
36879         lanesObj.forward[i][key] = l;
36880     });
36881     if (data.backward) data.backward.forEach(function(l, i) {
36882         if (!lanesObj.backward[i]) lanesObj.backward[i] = {};
36883         lanesObj.backward[i][key] = l;
36884     });
36885     if (data.unspecified) data.unspecified.forEach(function(l, i) {
36886         if (!lanesObj.unspecified[i]) lanesObj.unspecified[i] = {};
36887         lanesObj.unspecified[i][key] = l;
36888     });
36889 }
36890
36891 var translations = Object.create(null);
36892
36893 var currentLocale = 'en';
36894 var textDirection = 'ltr';
36895
36896 function setLocale(_) {
36897     if (translations[_] !== undefined) {
36898         currentLocale = _;
36899     } else if (translations[_.split('-')[0]]) {
36900         currentLocale = _.split('-')[0];
36901     }
36902 }
36903
36904 function addTranslation(id, value) {
36905     translations[id] = value;
36906 }
36907
36908 /**
36909  * Given a string identifier, try to find that string in the current
36910  * language, and return it.
36911  *
36912  * @param {string} s string identifier
36913  * @returns {string?} locale string
36914  */
36915 function t(s, o, loc) {
36916     loc = loc || currentLocale;
36917
36918     var path = s.split('.').reverse();
36919     var rep = translations[loc];
36920
36921     while (rep !== undefined && path.length) rep = rep[path.pop()];
36922
36923     if (rep !== undefined) {
36924         if (o) for (var k in o) rep = rep.replace('{' + k + '}', o[k]);
36925         return rep;
36926     }
36927
36928     if (loc !== 'en') {
36929         return t(s, o, 'en');
36930     }
36931
36932     if (o && 'default' in o) {
36933         return o.default;
36934     }
36935
36936     var missing = 'Missing ' + loc + ' translation: ' + s;
36937     if (typeof console !== 'undefined') console.error(missing); // eslint-disable-line
36938
36939     return missing;
36940 }
36941
36942 /**
36943  * Given string 'ltr' or 'rtl', save that setting
36944  *
36945  * @param {string} s ltr or rtl
36946  */
36947
36948 function setTextDirection(dir) {
36949     textDirection = dir;
36950 }
36951
36952 var detected;
36953
36954 function utilDetect(force) {
36955     if (detected && !force) return detected;
36956     detected = {};
36957
36958     var ua = navigator.userAgent,
36959         m = null;
36960
36961     m = ua.match(/(edge)\/?\s*(\.?\d+(\.\d+)*)/i);   // Edge
36962     if (m !== null) {
36963         detected.browser = m[1];
36964         detected.version = m[2];
36965     }
36966     if (!detected.browser) {
36967         m = ua.match(/Trident\/.*rv:([0-9]{1,}[\.0-9]{0,})/i);   // IE11
36968         if (m !== null) {
36969             detected.browser = 'msie';
36970             detected.version = m[1];
36971         }
36972     }
36973     if (!detected.browser) {
36974         m = ua.match(/(opr)\/?\s*(\.?\d+(\.\d+)*)/i);   // Opera 15+
36975         if (m !== null) {
36976             detected.browser = 'Opera';
36977             detected.version = m[2];
36978         }
36979     }
36980     if (!detected.browser) {
36981         m = ua.match(/(opera|chrome|safari|firefox|msie)\/?\s*(\.?\d+(\.\d+)*)/i);
36982         if (m !== null) {
36983             detected.browser = m[1];
36984             detected.version = m[2];
36985             m = ua.match(/version\/([\.\d]+)/i);
36986             if (m !== null) detected.version = m[1];
36987         }
36988     }
36989     if (!detected.browser) {
36990         detected.browser = navigator.appName;
36991         detected.version = navigator.appVersion;
36992     }
36993
36994     // keep major.minor version only..
36995     detected.version = detected.version.split(/\W/).slice(0,2).join('.');
36996
36997     if (detected.browser.toLowerCase() === 'msie') {
36998         detected.ie = true;
36999         detected.browser = 'Internet Explorer';
37000         detected.support = parseFloat(detected.version) >= 11;
37001     } else {
37002         detected.ie = false;
37003         detected.support = true;
37004     }
37005
37006     // Added due to incomplete svg style support. See #715
37007     detected.opera = (detected.browser.toLowerCase() === 'opera' && parseFloat(detected.version) < 15 );
37008
37009     detected.locale = (navigator.languages && navigator.languages.length)
37010         ? navigator.languages[0] : (navigator.language || navigator.userLanguage || 'en-US');
37011
37012     // Loaded locale is stored in currentLocale
37013     // return that instead (except in the situation where 'en' might override 'en-US')
37014     var loadedLocale = currentLocale || 'en';
37015     if (loadedLocale !== 'en') {
37016         detected.locale = loadedLocale;
37017     }
37018
37019     // detect text direction
37020     var q = utilStringQs(window.location.hash.substring(1));
37021     if (['ar', 'fa', 'iw', 'dv'].indexOf(detected.locale.split('-')[0]) > -1 || q.hasOwnProperty('rtl')) {
37022         detected.textDirection = 'rtl';
37023     } else {
37024         detected.textDirection = 'ltr';
37025     }
37026     setTextDirection(detected.textDirection);
37027
37028     detected.host = window.location && (window.location.origin + window.location.pathname);
37029
37030     detected.filedrop = (window.FileReader && 'ondrop' in window);
37031
37032     function nav(x) {
37033         return navigator.userAgent.indexOf(x) !== -1;
37034     }
37035
37036     if (nav('Win')) {
37037         detected.os = 'win';
37038         detected.platform = 'Windows';
37039     }
37040     else if (nav('Mac')) {
37041         detected.os = 'mac';
37042         detected.platform = 'Macintosh';
37043     }
37044     else if (nav('X11') || nav('Linux')) {
37045         detected.os = 'linux';
37046         detected.platform = 'Linux';
37047     }
37048     else {
37049         detected.os = 'win';
37050         detected.platform = 'Unknown';
37051     }
37052
37053     return detected;
37054 }
37055
37056 var remove$1 = removeDiacritics;
37057
37058 var replacementList = [
37059   {
37060     base: ' ',
37061     chars: "\u00A0",
37062   }, {
37063     base: '0',
37064     chars: "\u07C0",
37065   }, {
37066     base: 'A',
37067     chars: "\u24B6\uFF21\u00C0\u00C1\u00C2\u1EA6\u1EA4\u1EAA\u1EA8\u00C3\u0100\u0102\u1EB0\u1EAE\u1EB4\u1EB2\u0226\u01E0\u00C4\u01DE\u1EA2\u00C5\u01FA\u01CD\u0200\u0202\u1EA0\u1EAC\u1EB6\u1E00\u0104\u023A\u2C6F",
37068   }, {
37069     base: 'AA',
37070     chars: "\uA732",
37071   }, {
37072     base: 'AE',
37073     chars: "\u00C6\u01FC\u01E2",
37074   }, {
37075     base: 'AO',
37076     chars: "\uA734",
37077   }, {
37078     base: 'AU',
37079     chars: "\uA736",
37080   }, {
37081     base: 'AV',
37082     chars: "\uA738\uA73A",
37083   }, {
37084     base: 'AY',
37085     chars: "\uA73C",
37086   }, {
37087     base: 'B',
37088     chars: "\u24B7\uFF22\u1E02\u1E04\u1E06\u0243\u0181",
37089   }, {
37090     base: 'C',
37091     chars: "\u24b8\uff23\uA73E\u1E08\u0106\u0043\u0108\u010A\u010C\u00C7\u0187\u023B",
37092   }, {
37093     base: 'D',
37094     chars: "\u24B9\uFF24\u1E0A\u010E\u1E0C\u1E10\u1E12\u1E0E\u0110\u018A\u0189\u1D05\uA779",
37095   }, {
37096     base: 'Dh',
37097     chars: "\u00D0",
37098   }, {
37099     base: 'DZ',
37100     chars: "\u01F1\u01C4",
37101   }, {
37102     base: 'Dz',
37103     chars: "\u01F2\u01C5",
37104   }, {
37105     base: 'E',
37106     chars: "\u025B\u24BA\uFF25\u00C8\u00C9\u00CA\u1EC0\u1EBE\u1EC4\u1EC2\u1EBC\u0112\u1E14\u1E16\u0114\u0116\u00CB\u1EBA\u011A\u0204\u0206\u1EB8\u1EC6\u0228\u1E1C\u0118\u1E18\u1E1A\u0190\u018E\u1D07",
37107   }, {
37108     base: 'F',
37109     chars: "\uA77C\u24BB\uFF26\u1E1E\u0191\uA77B",
37110   }, {
37111     base: 'G',
37112     chars: "\u24BC\uFF27\u01F4\u011C\u1E20\u011E\u0120\u01E6\u0122\u01E4\u0193\uA7A0\uA77D\uA77E\u0262",
37113   }, {
37114     base: 'H',
37115     chars: "\u24BD\uFF28\u0124\u1E22\u1E26\u021E\u1E24\u1E28\u1E2A\u0126\u2C67\u2C75\uA78D",
37116   }, {
37117     base: 'I',
37118     chars: "\u24BE\uFF29\xCC\xCD\xCE\u0128\u012A\u012C\u0130\xCF\u1E2E\u1EC8\u01CF\u0208\u020A\u1ECA\u012E\u1E2C\u0197",
37119   }, {
37120     base: 'J',
37121     chars: "\u24BF\uFF2A\u0134\u0248\u0237",
37122   }, {
37123     base: 'K',
37124     chars: "\u24C0\uFF2B\u1E30\u01E8\u1E32\u0136\u1E34\u0198\u2C69\uA740\uA742\uA744\uA7A2",
37125   }, {
37126     base: 'L',
37127     chars: "\u24C1\uFF2C\u013F\u0139\u013D\u1E36\u1E38\u013B\u1E3C\u1E3A\u0141\u023D\u2C62\u2C60\uA748\uA746\uA780",
37128   }, {
37129     base: 'LJ',
37130     chars: "\u01C7",
37131   }, {
37132     base: 'Lj',
37133     chars: "\u01C8",
37134   }, {
37135     base: 'M',
37136     chars: "\u24C2\uFF2D\u1E3E\u1E40\u1E42\u2C6E\u019C\u03FB",
37137   }, {
37138     base: 'N',
37139     chars: "\uA7A4\u0220\u24C3\uFF2E\u01F8\u0143\xD1\u1E44\u0147\u1E46\u0145\u1E4A\u1E48\u019D\uA790\u1D0E",
37140   }, {
37141     base: 'NJ',
37142     chars: "\u01CA",
37143   }, {
37144     base: 'Nj',
37145     chars: "\u01CB",
37146   }, {
37147     base: 'O',
37148     chars: "\u24C4\uFF2F\xD2\xD3\xD4\u1ED2\u1ED0\u1ED6\u1ED4\xD5\u1E4C\u022C\u1E4E\u014C\u1E50\u1E52\u014E\u022E\u0230\xD6\u022A\u1ECE\u0150\u01D1\u020C\u020E\u01A0\u1EDC\u1EDA\u1EE0\u1EDE\u1EE2\u1ECC\u1ED8\u01EA\u01EC\xD8\u01FE\u0186\u019F\uA74A\uA74C",
37149   }, {
37150     base: 'OE',
37151     chars: "\u0152",
37152   }, {
37153     base: 'OI',
37154     chars: "\u01A2",
37155   }, {
37156     base: 'OO',
37157     chars: "\uA74E",
37158   }, {
37159     base: 'OU',
37160     chars: "\u0222",
37161   }, {
37162     base: 'P',
37163     chars: "\u24C5\uFF30\u1E54\u1E56\u01A4\u2C63\uA750\uA752\uA754",
37164   }, {
37165     base: 'Q',
37166     chars: "\u24C6\uFF31\uA756\uA758\u024A",
37167   }, {
37168     base: 'R',
37169     chars: "\u24C7\uFF32\u0154\u1E58\u0158\u0210\u0212\u1E5A\u1E5C\u0156\u1E5E\u024C\u2C64\uA75A\uA7A6\uA782",
37170   }, {
37171     base: 'S',
37172     chars: "\u24C8\uFF33\u1E9E\u015A\u1E64\u015C\u1E60\u0160\u1E66\u1E62\u1E68\u0218\u015E\u2C7E\uA7A8\uA784",
37173   }, {
37174     base: 'T',
37175     chars: "\u24C9\uFF34\u1E6A\u0164\u1E6C\u021A\u0162\u1E70\u1E6E\u0166\u01AC\u01AE\u023E\uA786",
37176   }, {
37177     base: 'Th',
37178     chars: "\u00DE",
37179   }, {
37180     base: 'TZ',
37181     chars: "\uA728",
37182   }, {
37183     base: 'U',
37184     chars: "\u24CA\uFF35\xD9\xDA\xDB\u0168\u1E78\u016A\u1E7A\u016C\xDC\u01DB\u01D7\u01D5\u01D9\u1EE6\u016E\u0170\u01D3\u0214\u0216\u01AF\u1EEA\u1EE8\u1EEE\u1EEC\u1EF0\u1EE4\u1E72\u0172\u1E76\u1E74\u0244",
37185   }, {
37186     base: 'V',
37187     chars: "\u24CB\uFF36\u1E7C\u1E7E\u01B2\uA75E\u0245",
37188   }, {
37189     base: 'VY',
37190     chars: "\uA760",
37191   }, {
37192     base: 'W',
37193     chars: "\u24CC\uFF37\u1E80\u1E82\u0174\u1E86\u1E84\u1E88\u2C72",
37194   }, {
37195     base: 'X',
37196     chars: "\u24CD\uFF38\u1E8A\u1E8C",
37197   }, {
37198     base: 'Y',
37199     chars: "\u24CE\uFF39\u1EF2\xDD\u0176\u1EF8\u0232\u1E8E\u0178\u1EF6\u1EF4\u01B3\u024E\u1EFE",
37200   }, {
37201     base: 'Z',
37202     chars: "\u24CF\uFF3A\u0179\u1E90\u017B\u017D\u1E92\u1E94\u01B5\u0224\u2C7F\u2C6B\uA762",
37203   }, {
37204     base: 'a',
37205     chars: "\u24D0\uFF41\u1E9A\u00E0\u00E1\u00E2\u1EA7\u1EA5\u1EAB\u1EA9\u00E3\u0101\u0103\u1EB1\u1EAF\u1EB5\u1EB3\u0227\u01E1\u00E4\u01DF\u1EA3\u00E5\u01FB\u01CE\u0201\u0203\u1EA1\u1EAD\u1EB7\u1E01\u0105\u2C65\u0250\u0251",
37206   }, {
37207     base: 'aa',
37208     chars: "\uA733",
37209   }, {
37210     base: 'ae',
37211     chars: "\u00E6\u01FD\u01E3",
37212   }, {
37213     base: 'ao',
37214     chars: "\uA735",
37215   }, {
37216     base: 'au',
37217     chars: "\uA737",
37218   }, {
37219     base: 'av',
37220     chars: "\uA739\uA73B",
37221   }, {
37222     base: 'ay',
37223     chars: "\uA73D",
37224   }, {
37225     base: 'b',
37226     chars: "\u24D1\uFF42\u1E03\u1E05\u1E07\u0180\u0183\u0253\u0182",
37227   }, {
37228     base: 'c',
37229     chars: "\uFF43\u24D2\u0107\u0109\u010B\u010D\u00E7\u1E09\u0188\u023C\uA73F\u2184",
37230   }, {
37231     base: 'd',
37232     chars: "\u24D3\uFF44\u1E0B\u010F\u1E0D\u1E11\u1E13\u1E0F\u0111\u018C\u0256\u0257\u018B\u13E7\u0501\uA7AA",
37233   }, {
37234     base: 'dh',
37235     chars: "\u00F0",
37236   }, {
37237     base: 'dz',
37238     chars: "\u01F3\u01C6",
37239   }, {
37240     base: 'e',
37241     chars: "\u24D4\uFF45\u00E8\u00E9\u00EA\u1EC1\u1EBF\u1EC5\u1EC3\u1EBD\u0113\u1E15\u1E17\u0115\u0117\u00EB\u1EBB\u011B\u0205\u0207\u1EB9\u1EC7\u0229\u1E1D\u0119\u1E19\u1E1B\u0247\u01DD",
37242   }, {
37243     base: 'f',
37244     chars: "\u24D5\uFF46\u1E1F\u0192",
37245   }, {
37246     base: 'ff',
37247     chars: "\uFB00",
37248   }, {
37249     base: 'fi',
37250     chars: "\uFB01",
37251   }, {
37252     base: 'fl',
37253     chars: "\uFB02",
37254   }, {
37255     base: 'ffi',
37256     chars: "\uFB03",
37257   }, {
37258     base: 'ffl',
37259     chars: "\uFB04",
37260   }, {
37261     base: 'g',
37262     chars: "\u24D6\uFF47\u01F5\u011D\u1E21\u011F\u0121\u01E7\u0123\u01E5\u0260\uA7A1\uA77F\u1D79",
37263   }, {
37264     base: 'h',
37265     chars: "\u24D7\uFF48\u0125\u1E23\u1E27\u021F\u1E25\u1E29\u1E2B\u1E96\u0127\u2C68\u2C76\u0265",
37266   }, {
37267     base: 'hv',
37268     chars: "\u0195",
37269   }, {
37270     base: 'i',
37271     chars: "\u24D8\uFF49\xEC\xED\xEE\u0129\u012B\u012D\xEF\u1E2F\u1EC9\u01D0\u0209\u020B\u1ECB\u012F\u1E2D\u0268\u0131",
37272   }, {
37273     base: 'j',
37274     chars: "\u24D9\uFF4A\u0135\u01F0\u0249",
37275   }, {
37276     base: 'k',
37277     chars: "\u24DA\uFF4B\u1E31\u01E9\u1E33\u0137\u1E35\u0199\u2C6A\uA741\uA743\uA745\uA7A3",
37278   }, {
37279     base: 'l',
37280     chars: "\u24DB\uFF4C\u0140\u013A\u013E\u1E37\u1E39\u013C\u1E3D\u1E3B\u017F\u0142\u019A\u026B\u2C61\uA749\uA781\uA747\u026D",
37281   }, {
37282     base: 'lj',
37283     chars: "\u01C9",
37284   }, {
37285     base: 'm',
37286     chars: "\u24DC\uFF4D\u1E3F\u1E41\u1E43\u0271\u026F",
37287   }, {
37288     base: 'n',
37289     chars: "\u24DD\uFF4E\u01F9\u0144\xF1\u1E45\u0148\u1E47\u0146\u1E4B\u1E49\u019E\u0272\u0149\uA791\uA7A5\u043B\u0509",
37290   }, {
37291     base: 'nj',
37292     chars: "\u01CC",
37293   }, {
37294     base: 'o',
37295     chars: "\u24DE\uFF4F\xF2\xF3\xF4\u1ED3\u1ED1\u1ED7\u1ED5\xF5\u1E4D\u022D\u1E4F\u014D\u1E51\u1E53\u014F\u022F\u0231\xF6\u022B\u1ECF\u0151\u01D2\u020D\u020F\u01A1\u1EDD\u1EDB\u1EE1\u1EDF\u1EE3\u1ECD\u1ED9\u01EB\u01ED\xF8\u01FF\uA74B\uA74D\u0275\u0254\u1D11",
37296   }, {
37297     base: 'oe',
37298     chars: "\u0153",
37299   }, {
37300     base: 'oi',
37301     chars: "\u01A3",
37302   }, {
37303     base: 'oo',
37304     chars: "\uA74F",
37305   }, {
37306     base: 'ou',
37307     chars: "\u0223",
37308   }, {
37309     base: 'p',
37310     chars: "\u24DF\uFF50\u1E55\u1E57\u01A5\u1D7D\uA751\uA753\uA755\u03C1",
37311   }, {
37312     base: 'q',
37313     chars: "\u24E0\uFF51\u024B\uA757\uA759",
37314   }, {
37315     base: 'r',
37316     chars: "\u24E1\uFF52\u0155\u1E59\u0159\u0211\u0213\u1E5B\u1E5D\u0157\u1E5F\u024D\u027D\uA75B\uA7A7\uA783",
37317   }, {
37318     base: 's',
37319     chars: "\u24E2\uFF53\u015B\u1E65\u015D\u1E61\u0161\u1E67\u1E63\u1E69\u0219\u015F\u023F\uA7A9\uA785\u1E9B\u0282",
37320   }, {
37321     base: 'ss',
37322     chars: "\xDF",
37323   }, {
37324     base: 't',
37325     chars: "\u24E3\uFF54\u1E6B\u1E97\u0165\u1E6D\u021B\u0163\u1E71\u1E6F\u0167\u01AD\u0288\u2C66\uA787",
37326   }, {
37327     base: 'th',
37328     chars: "\u00FE",
37329   }, {
37330     base: 'tz',
37331     chars: "\uA729",
37332   }, {
37333     base: 'u',
37334     chars: "\u24E4\uFF55\xF9\xFA\xFB\u0169\u1E79\u016B\u1E7B\u016D\xFC\u01DC\u01D8\u01D6\u01DA\u1EE7\u016F\u0171\u01D4\u0215\u0217\u01B0\u1EEB\u1EE9\u1EEF\u1EED\u1EF1\u1EE5\u1E73\u0173\u1E77\u1E75\u0289",
37335   }, {
37336     base: 'v',
37337     chars: "\u24E5\uFF56\u1E7D\u1E7F\u028B\uA75F\u028C",
37338   }, {
37339     base: 'vy',
37340     chars: "\uA761",
37341   }, {
37342     base: 'w',
37343     chars: "\u24E6\uFF57\u1E81\u1E83\u0175\u1E87\u1E85\u1E98\u1E89\u2C73",
37344   }, {
37345     base: 'x',
37346     chars: "\u24E7\uFF58\u1E8B\u1E8D",
37347   }, {
37348     base: 'y',
37349     chars: "\u24E8\uFF59\u1EF3\xFD\u0177\u1EF9\u0233\u1E8F\xFF\u1EF7\u1E99\u1EF5\u01B4\u024F\u1EFF",
37350   }, {
37351     base: 'z',
37352     chars: "\u24E9\uFF5A\u017A\u1E91\u017C\u017E\u1E93\u1E95\u01B6\u0225\u0240\u2C6C\uA763",
37353   }
37354 ];
37355
37356 var diacriticsMap = {};
37357 for (var i = 0; i < replacementList.length; i += 1) {
37358   var chars = replacementList[i].chars;
37359   for (var j = 0; j < chars.length; j += 1) {
37360     diacriticsMap[chars[j]] = replacementList[i].base;
37361   }
37362 }
37363
37364 function removeDiacritics(str) {
37365   return str.replace(/[^\u0000-\u007e]/g, function(c) {
37366     return diacriticsMap[c] || c;
37367   });
37368 }
37369
37370 function utilTagText(entity) {
37371     return entries(entity.tags).map(function(e) {
37372         return e.key + '=' + e.value;
37373     }).join(', ');
37374 }
37375
37376
37377 function utilEntitySelector(ids) {
37378     return ids.length ? '.' + ids.join(',.') : 'nothing';
37379 }
37380
37381
37382 function utilEntityOrMemberSelector(ids, graph) {
37383     var s = utilEntitySelector(ids);
37384
37385     ids.forEach(function(id) {
37386         var entity = graph.hasEntity(id);
37387         if (entity && entity.type === 'relation') {
37388             entity.members.forEach(function(member) {
37389                 s += ',.' + member.id;
37390             });
37391         }
37392     });
37393
37394     return s;
37395 }
37396
37397
37398 function utilDisplayName(entity) {
37399     var localizedNameKey = 'name:' + utilDetect().locale.toLowerCase().split('-')[0],
37400         name = entity.tags[localizedNameKey] || entity.tags.name || '',
37401         network = entity.tags.cycle_network || entity.tags.network;
37402     if (!name && entity.tags.ref) {
37403         name = entity.tags.ref;
37404         if (network) {
37405             name = network + ' ' + name;
37406         }
37407     }
37408     return name;
37409 }
37410
37411
37412 function utilDisplayType(id) {
37413     return {
37414         n: t('inspector.node'),
37415         w: t('inspector.way'),
37416         r: t('inspector.relation')
37417     }[id.charAt(0)];
37418 }
37419
37420
37421 function utilStringQs(str) {
37422     return str.split('&').reduce(function(obj, pair){
37423         var parts = pair.split('=');
37424         if (parts.length === 2) {
37425             obj[parts[0]] = (null === parts[1]) ? '' : decodeURIComponent(parts[1]);
37426         }
37427         return obj;
37428     }, {});
37429 }
37430
37431
37432 function utilQsString(obj, noencode) {
37433     function softEncode(s) {
37434       // encode everything except special characters used in certain hash parameters:
37435       // "/" in map states, ":", ",", {" and "}" in background
37436       return encodeURIComponent(s).replace(/(%2F|%3A|%2C|%7B|%7D)/g, decodeURIComponent);
37437     }
37438     return Object.keys(obj).sort().map(function(key) {
37439         return encodeURIComponent(key) + '=' + (
37440             noencode ? softEncode(obj[key]) : encodeURIComponent(obj[key]));
37441     }).join('&');
37442 }
37443
37444
37445 function utilPrefixDOMProperty(property) {
37446     var prefixes = ['webkit', 'ms', 'moz', 'o'],
37447         i = -1,
37448         n = prefixes.length,
37449         s = document.body;
37450
37451     if (property in s)
37452         return property;
37453
37454     property = property.substr(0, 1).toUpperCase() + property.substr(1);
37455
37456     while (++i < n)
37457         if (prefixes[i] + property in s)
37458             return prefixes[i] + property;
37459
37460     return false;
37461 }
37462
37463
37464 function utilPrefixCSSProperty(property) {
37465     var prefixes = ['webkit', 'ms', 'Moz', 'O'],
37466         i = -1,
37467         n = prefixes.length,
37468         s = document.body.style;
37469
37470     if (property.toLowerCase() in s)
37471         return property.toLowerCase();
37472
37473     while (++i < n)
37474         if (prefixes[i] + property in s)
37475             return '-' + prefixes[i].toLowerCase() + property.replace(/([A-Z])/g, '-$1').toLowerCase();
37476
37477     return false;
37478 }
37479
37480
37481 var transformProperty;
37482 function utilSetTransform(el, x, y, scale) {
37483     var prop = transformProperty = transformProperty || utilPrefixCSSProperty('Transform'),
37484         translate = utilDetect().opera ?
37485             'translate('   + x + 'px,' + y + 'px)' :
37486             'translate3d(' + x + 'px,' + y + 'px,0)';
37487     return el.style(prop, translate + (scale ? ' scale(' + scale + ')' : ''));
37488 }
37489
37490
37491 // Calculates Levenshtein distance between two strings
37492 // see:  https://en.wikipedia.org/wiki/Levenshtein_distance
37493 // first converts the strings to lowercase and replaces diacritic marks with ascii equilivants.
37494 function utilEditDistance(a, b) {
37495     a = remove$1(a.toLowerCase());
37496     b = remove$1(b.toLowerCase());
37497     if (a.length === 0) return b.length;
37498     if (b.length === 0) return a.length;
37499     var matrix = [];
37500     for (var i = 0; i <= b.length; i++) { matrix[i] = [i]; }
37501     for (var j = 0; j <= a.length; j++) { matrix[0][j] = j; }
37502     for (i = 1; i <= b.length; i++) {
37503         for (j = 1; j <= a.length; j++) {
37504             if (b.charAt(i-1) === a.charAt(j-1)) {
37505                 matrix[i][j] = matrix[i-1][j-1];
37506             } else {
37507                 matrix[i][j] = Math.min(matrix[i-1][j-1] + 1, // substitution
37508                     Math.min(matrix[i][j-1] + 1, // insertion
37509                     matrix[i-1][j] + 1)); // deletion
37510             }
37511         }
37512     }
37513     return matrix[b.length][a.length];
37514 }
37515
37516
37517 // a d3.mouse-alike which
37518 // 1. Only works on HTML elements, not SVG
37519 // 2. Does not cause style recalculation
37520 function utilFastMouse(container) {
37521     var rect = container.getBoundingClientRect(),
37522         rectLeft = rect.left,
37523         rectTop = rect.top,
37524         clientLeft = +container.clientLeft,
37525         clientTop = +container.clientTop;
37526     if (textDirection === 'rtl') {
37527         rectLeft = 0;
37528     }
37529     return function(e) {
37530         return [
37531             e.clientX - rectLeft - clientLeft,
37532             e.clientY - rectTop - clientTop];
37533     };
37534 }
37535
37536
37537 /* eslint-disable no-proto */
37538 var utilGetPrototypeOf = Object.getPrototypeOf || function(obj) { return obj.__proto__; };
37539 /* eslint-enable no-proto */
37540
37541
37542 function utilAsyncMap(inputs, func, callback) {
37543     var remaining = inputs.length,
37544         results = [],
37545         errors = [];
37546
37547     inputs.forEach(function(d, i) {
37548         func(d, function done(err, data) {
37549             errors[i] = err;
37550             results[i] = data;
37551             remaining--;
37552             if (!remaining) callback(errors, results);
37553         });
37554     });
37555 }
37556
37557
37558 // wraps an index to an interval [0..length-1]
37559 function utilWrap(index, length) {
37560     if (index < 0)
37561         index += Math.ceil(-index/length)*length;
37562     return index % length;
37563 }
37564
37565
37566 /**
37567  * a replacement for functor
37568  *
37569  * @param {*} value any value
37570  * @returns {Function} a function that returns that value or the value if it's a function
37571  */
37572 function utilFunctor(value) {
37573     if (typeof value === 'function') return value;
37574     return function() {
37575         return value;
37576     };
37577 }
37578
37579 // A per-domain session mutex backed by a cookie and dead man's
37580 // switch. If the session crashes, the mutex will auto-release
37581 // after 5 seconds.
37582
37583 function utilSessionMutex(name) {
37584     var mutex = {},
37585         intervalID;
37586
37587     function renew() {
37588         var expires = new Date();
37589         expires.setSeconds(expires.getSeconds() + 5);
37590         document.cookie = name + '=1; expires=' + expires.toUTCString();
37591     }
37592
37593     mutex.lock = function() {
37594         if (intervalID) return true;
37595         var cookie = document.cookie.replace(new RegExp('(?:(?:^|.*;)\\s*' + name + '\\s*\\=\\s*([^;]*).*$)|^.*$'), '$1');
37596         if (cookie) return false;
37597         renew();
37598         intervalID = window.setInterval(renew, 4000);
37599         return true;
37600     };
37601
37602     mutex.unlock = function() {
37603         if (!intervalID) return;
37604         document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:00 GMT';
37605         clearInterval(intervalID);
37606         intervalID = null;
37607     };
37608
37609     mutex.locked = function() {
37610         return !!intervalID;
37611     };
37612
37613     return mutex;
37614 }
37615
37616 function utilSuggestNames(preset, suggestions) {
37617     preset = preset.id.split('/', 2);
37618     var k = preset[0],
37619         v = preset[1];
37620
37621     return function(value, callback) {
37622         var result = [];
37623         if (value && value.length > 2) {
37624             if (suggestions[k] && suggestions[k][v]) {
37625                 for (var sugg in suggestions[k][v]) {
37626                     var dist = utilEditDistance(value, sugg.substring(0, value.length));
37627                     if (dist < 3) {
37628                         result.push({
37629                             title: sugg,
37630                             value: sugg,
37631                             dist: dist
37632                         });
37633                     }
37634                 }
37635             }
37636             result.sort(function(a, b) {
37637                 return a.dist - b.dist;
37638             });
37639         }
37640         result = result.slice(0,3);
37641         callback(result);
37642     };
37643 }
37644
37645 function utilTriggerEvent(target, type) {
37646     target.each(function() {
37647         var evt = document.createEvent('HTMLEvents');
37648         evt.initEvent(type, true, true);
37649         this.dispatchEvent(evt);
37650     });
37651 }
37652
37653 // Like selection.property('value', ...), but avoids no-op value sets,
37654 // which can result in layout/repaint thrashing in some situations.
37655 function utilGetSetValue(selection, value) {
37656     function d3_selection_value(value) {
37657         function valueNull() {
37658             delete this.value;
37659         }
37660
37661         function valueConstant() {
37662             if (this.value !== value) {
37663                 this.value = value;
37664             }
37665         }
37666
37667         function valueFunction() {
37668             var x = value.apply(this, arguments);
37669             if (x == null) {
37670                 delete this.value;
37671             } else if (this.value !== x) {
37672                 this.value = x;
37673             }
37674         }
37675
37676         return value == null
37677             ? valueNull : (typeof value === 'function'
37678             ? valueFunction : valueConstant);
37679     }
37680
37681     if (arguments.length === 1) {
37682         return selection.property('value');
37683     }
37684
37685     return selection.each(d3_selection_value(value));
37686 }
37687
37688 function validationDeprecatedTag() {
37689
37690     var validation = function(changes) {
37691         var warnings = [];
37692         for (var i = 0; i < changes.created.length; i++) {
37693             var change = changes.created[i],
37694                 deprecatedTags = change.deprecatedTags();
37695
37696             if (!lodash.isEmpty(deprecatedTags)) {
37697                 var tags = utilTagText({ tags: deprecatedTags });
37698                 warnings.push({
37699                     id: 'deprecated_tags',
37700                     message: t('validations.deprecated_tags', { tags: tags }),
37701                     entity: change
37702                 });
37703             }
37704         }
37705
37706         return warnings;
37707     };
37708
37709
37710     return validation;
37711 }
37712
37713 function validationManyDeletions() {
37714     var threshold = 100;
37715
37716     var validation = function(changes) {
37717         var warnings = [];
37718         if (changes.deleted.length > threshold) {
37719             warnings.push({
37720                 id: 'many_deletions',
37721                 message: t('validations.many_deletions', { n: changes.deleted.length })
37722             });
37723         }
37724
37725         return warnings;
37726     };
37727
37728
37729     return validation;
37730 }
37731
37732 function validationMissingTag() {
37733
37734     // Slightly stricter check than Entity#isUsed (#3091)
37735     function hasTags(entity, graph) {
37736         return lodash.without(Object.keys(entity.tags), 'area', 'name').length > 0 ||
37737             graph.parentRelations(entity).length > 0;
37738     }
37739
37740     var validation = function(changes, graph) {
37741         var warnings = [];
37742         for (var i = 0; i < changes.created.length; i++) {
37743             var change = changes.created[i],
37744                 geometry = change.geometry(graph);
37745
37746             if ((geometry === 'point' || geometry === 'line' || geometry === 'area') && !hasTags(change, graph)) {
37747                 warnings.push({
37748                     id: 'missing_tag',
37749                     message: t('validations.untagged_' + geometry),
37750                     tooltip: t('validations.untagged_' + geometry + '_tooltip'),
37751                     entity: change
37752                 });
37753             }
37754         }
37755
37756         return warnings;
37757     };
37758
37759
37760     return validation;
37761 }
37762
37763 // https://github.com/openstreetmap/josm/blob/mirror/src/org/
37764 // openstreetmap/josm/data/validation/tests/UnclosedWays.java#L80
37765 function validationTagSuggestsArea() {
37766
37767     function tagSuggestsArea(tags) {
37768         if (lodash.isEmpty(tags)) return false;
37769
37770         var presence = ['landuse', 'amenities', 'tourism', 'shop'];
37771         for (var i = 0; i < presence.length; i++) {
37772             if (tags[presence[i]] !== undefined) {
37773                 return presence[i] + '=' + tags[presence[i]];
37774             }
37775         }
37776
37777         if (tags.building && tags.building === 'yes') return 'building=yes';
37778     }
37779
37780
37781     var validation = function(changes, graph) {
37782         var warnings = [];
37783         for (var i = 0; i < changes.created.length; i++) {
37784             var change = changes.created[i],
37785                 geometry = change.geometry(graph),
37786                 suggestion = (geometry === 'line' ? tagSuggestsArea(change.tags) : undefined);
37787
37788             if (suggestion) {
37789                 warnings.push({
37790                     id: 'tag_suggests_area',
37791                     message: t('validations.tag_suggests_area', { tag: suggestion }),
37792                     entity: change
37793                 });
37794             }
37795         }
37796
37797         return warnings;
37798     };
37799
37800
37801     return validation;
37802 }
37803
37804
37805
37806 var Validations = Object.freeze({
37807         validationDeprecatedTag: validationDeprecatedTag,
37808         validationManyDeletions: validationManyDeletions,
37809         validationMissingTag: validationMissingTag,
37810         validationTagSuggestsArea: validationTagSuggestsArea
37811 });
37812
37813 /*
37814     iD.Difference represents the difference between two graphs.
37815     It knows how to calculate the set of entities that were
37816     created, modified, or deleted, and also contains the logic
37817     for recursively extending a difference to the complete set
37818     of entities that will require a redraw, taking into account
37819     child and parent relationships.
37820  */
37821 function coreDifference(base, head) {
37822     var changes = {},
37823         difference = {},
37824         length = 0;
37825
37826
37827     function changed(h, b) {
37828         return h !== b && !lodash.isEqual(lodash.omit(h, 'v'), lodash.omit(b, 'v'));
37829     }
37830
37831
37832     lodash.each(head.entities, function(h, id) {
37833         var b = base.entities[id];
37834         if (changed(h, b)) {
37835             changes[id] = {base: b, head: h};
37836             length++;
37837         }
37838     });
37839
37840
37841     lodash.each(base.entities, function(b, id) {
37842         var h = head.entities[id];
37843         if (!changes[id] && changed(h, b)) {
37844             changes[id] = {base: b, head: h};
37845             length++;
37846         }
37847     });
37848
37849
37850     function addParents(parents, result) {
37851         for (var i = 0; i < parents.length; i++) {
37852             var parent = parents[i];
37853
37854             if (parent.id in result)
37855                 continue;
37856
37857             result[parent.id] = parent;
37858             addParents(head.parentRelations(parent), result);
37859         }
37860     }
37861
37862
37863     difference.length = function() {
37864         return length;
37865     };
37866
37867
37868     difference.changes = function() {
37869         return changes;
37870     };
37871
37872
37873     difference.extantIDs = function() {
37874         var result = [];
37875         lodash.each(changes, function(change, id) {
37876             if (change.head) result.push(id);
37877         });
37878         return result;
37879     };
37880
37881
37882     difference.modified = function() {
37883         var result = [];
37884         lodash.each(changes, function(change) {
37885             if (change.base && change.head) result.push(change.head);
37886         });
37887         return result;
37888     };
37889
37890
37891     difference.created = function() {
37892         var result = [];
37893         lodash.each(changes, function(change) {
37894             if (!change.base && change.head) result.push(change.head);
37895         });
37896         return result;
37897     };
37898
37899
37900     difference.deleted = function() {
37901         var result = [];
37902         lodash.each(changes, function(change) {
37903             if (change.base && !change.head) result.push(change.base);
37904         });
37905         return result;
37906     };
37907
37908
37909     difference.summary = function() {
37910         var relevant = {};
37911
37912         function addEntity(entity, graph, changeType) {
37913             relevant[entity.id] = {
37914                 entity: entity,
37915                 graph: graph,
37916                 changeType: changeType
37917             };
37918         }
37919
37920         function addParents(entity) {
37921             var parents = head.parentWays(entity);
37922             for (var j = parents.length - 1; j >= 0; j--) {
37923                 var parent = parents[j];
37924                 if (!(parent.id in relevant)) addEntity(parent, head, 'modified');
37925             }
37926         }
37927
37928         lodash.each(changes, function(change) {
37929             if (change.head && change.head.geometry(head) !== 'vertex') {
37930                 addEntity(change.head, head, change.base ? 'modified' : 'created');
37931
37932             } else if (change.base && change.base.geometry(base) !== 'vertex') {
37933                 addEntity(change.base, base, 'deleted');
37934
37935             } else if (change.base && change.head) { // modified vertex
37936                 var moved    = !lodash.isEqual(change.base.loc,  change.head.loc),
37937                     retagged = !lodash.isEqual(change.base.tags, change.head.tags);
37938
37939                 if (moved) {
37940                     addParents(change.head);
37941                 }
37942
37943                 if (retagged || (moved && change.head.hasInterestingTags())) {
37944                     addEntity(change.head, head, 'modified');
37945                 }
37946
37947             } else if (change.head && change.head.hasInterestingTags()) { // created vertex
37948                 addEntity(change.head, head, 'created');
37949
37950             } else if (change.base && change.base.hasInterestingTags()) { // deleted vertex
37951                 addEntity(change.base, base, 'deleted');
37952             }
37953         });
37954
37955         return values(relevant);
37956     };
37957
37958
37959     difference.complete = function(extent$$1) {
37960         var result = {}, id, change;
37961
37962         for (id in changes) {
37963             change = changes[id];
37964
37965             var h = change.head,
37966                 b = change.base,
37967                 entity = h || b;
37968
37969             if (extent$$1 &&
37970                 (!h || !h.intersects(extent$$1, head)) &&
37971                 (!b || !b.intersects(extent$$1, base)))
37972                 continue;
37973
37974             result[id] = h;
37975
37976             if (entity.type === 'way') {
37977                 var nh = h ? h.nodes : [],
37978                     nb = b ? b.nodes : [],
37979                     diff, i;
37980
37981                 diff = lodash.difference(nh, nb);
37982                 for (i = 0; i < diff.length; i++) {
37983                     result[diff[i]] = head.hasEntity(diff[i]);
37984                 }
37985
37986                 diff = lodash.difference(nb, nh);
37987                 for (i = 0; i < diff.length; i++) {
37988                     result[diff[i]] = head.hasEntity(diff[i]);
37989                 }
37990             }
37991
37992             addParents(head.parentWays(entity), result);
37993             addParents(head.parentRelations(entity), result);
37994         }
37995
37996         return result;
37997     };
37998
37999
38000     return difference;
38001 }
38002
38003 function coreGraph$$1(other, mutable) {
38004     if (!(this instanceof coreGraph$$1)) return new coreGraph$$1(other, mutable);
38005
38006     if (other instanceof coreGraph$$1) {
38007         var base = other.base();
38008         this.entities = lodash.assign(Object.create(base.entities), other.entities);
38009         this._parentWays = lodash.assign(Object.create(base.parentWays), other._parentWays);
38010         this._parentRels = lodash.assign(Object.create(base.parentRels), other._parentRels);
38011
38012     } else {
38013         this.entities = Object.create({});
38014         this._parentWays = Object.create({});
38015         this._parentRels = Object.create({});
38016         this.rebase(other || [], [this]);
38017     }
38018
38019     this.transients = {};
38020     this._childNodes = {};
38021     this.frozen = !mutable;
38022 }
38023
38024
38025 coreGraph$$1.prototype = {
38026
38027     hasEntity: function(id) {
38028         return this.entities[id];
38029     },
38030
38031
38032     entity: function(id) {
38033         var entity = this.entities[id];
38034         if (!entity) {
38035             throw new Error('entity ' + id + ' not found');
38036         }
38037         return entity;
38038     },
38039
38040
38041     transient: function(entity, key, fn) {
38042         var id = entity.id,
38043             transients = this.transients[id] ||
38044             (this.transients[id] = {});
38045
38046         if (transients[key] !== undefined) {
38047             return transients[key];
38048         }
38049
38050         transients[key] = fn.call(entity);
38051
38052         return transients[key];
38053     },
38054
38055
38056     parentWays: function(entity) {
38057         var parents = this._parentWays[entity.id],
38058             result = [];
38059
38060         if (parents) {
38061             for (var i = 0; i < parents.length; i++) {
38062                 result.push(this.entity(parents[i]));
38063             }
38064         }
38065         return result;
38066     },
38067
38068
38069     isPoi: function(entity) {
38070         var parentWays = this._parentWays[entity.id];
38071         return !parentWays || parentWays.length === 0;
38072     },
38073
38074
38075     isShared: function(entity) {
38076         var parentWays = this._parentWays[entity.id];
38077         return parentWays && parentWays.length > 1;
38078     },
38079
38080
38081     parentRelations: function(entity) {
38082         var parents = this._parentRels[entity.id],
38083             result = [];
38084
38085         if (parents) {
38086             for (var i = 0; i < parents.length; i++) {
38087                 result.push(this.entity(parents[i]));
38088             }
38089         }
38090         return result;
38091     },
38092
38093
38094     childNodes: function(entity) {
38095         if (this._childNodes[entity.id]) return this._childNodes[entity.id];
38096         if (!entity.nodes) return [];
38097
38098         var nodes = [];
38099         for (var i = 0; i < entity.nodes.length; i++) {
38100             nodes[i] = this.entity(entity.nodes[i]);
38101         }
38102
38103         if (debug) Object.freeze(nodes);
38104
38105         this._childNodes[entity.id] = nodes;
38106         return this._childNodes[entity.id];
38107     },
38108
38109
38110     base: function() {
38111         return {
38112             'entities': utilGetPrototypeOf(this.entities),
38113             'parentWays': utilGetPrototypeOf(this._parentWays),
38114             'parentRels': utilGetPrototypeOf(this._parentRels)
38115         };
38116     },
38117
38118
38119     // Unlike other graph methods, rebase mutates in place. This is because it
38120     // is used only during the history operation that merges newly downloaded
38121     // data into each state. To external consumers, it should appear as if the
38122     // graph always contained the newly downloaded data.
38123     rebase: function(entities, stack, force) {
38124         var base = this.base(),
38125             i, j, k, id;
38126
38127         for (i = 0; i < entities.length; i++) {
38128             var entity = entities[i];
38129
38130             if (!entity.visible || (!force && base.entities[entity.id]))
38131                 continue;
38132
38133             // Merging data into the base graph
38134             base.entities[entity.id] = entity;
38135             this._updateCalculated(undefined, entity, base.parentWays, base.parentRels);
38136
38137             // Restore provisionally-deleted nodes that are discovered to have an extant parent
38138             if (entity.type === 'way') {
38139                 for (j = 0; j < entity.nodes.length; j++) {
38140                     id = entity.nodes[j];
38141                     for (k = 1; k < stack.length; k++) {
38142                         var ents = stack[k].entities;
38143                         if (ents.hasOwnProperty(id) && ents[id] === undefined) {
38144                             delete ents[id];
38145                         }
38146                     }
38147                 }
38148             }
38149         }
38150
38151         for (i = 0; i < stack.length; i++) {
38152             stack[i]._updateRebased();
38153         }
38154     },
38155
38156
38157     _updateRebased: function() {
38158         var base = this.base(),
38159             i, k, child, id, keys;
38160
38161         keys = Object.keys(this._parentWays);
38162         for (i = 0; i < keys.length; i++) {
38163             child = keys[i];
38164             if (base.parentWays[child]) {
38165                 for (k = 0; k < base.parentWays[child].length; k++) {
38166                     id = base.parentWays[child][k];
38167                     if (!this.entities.hasOwnProperty(id) && !lodash.includes(this._parentWays[child], id)) {
38168                         this._parentWays[child].push(id);
38169                     }
38170                 }
38171             }
38172         }
38173
38174         keys = Object.keys(this._parentRels);
38175         for (i = 0; i < keys.length; i++) {
38176             child = keys[i];
38177             if (base.parentRels[child]) {
38178                 for (k = 0; k < base.parentRels[child].length; k++) {
38179                     id = base.parentRels[child][k];
38180                     if (!this.entities.hasOwnProperty(id) && !lodash.includes(this._parentRels[child], id)) {
38181                         this._parentRels[child].push(id);
38182                     }
38183                 }
38184             }
38185         }
38186
38187         this.transients = {};
38188
38189         // this._childNodes is not updated, under the assumption that
38190         // ways are always downloaded with their child nodes.
38191     },
38192
38193
38194     // Updates calculated properties (parentWays, parentRels) for the specified change
38195     _updateCalculated: function(oldentity, entity, parentWays, parentRels) {
38196
38197         parentWays = parentWays || this._parentWays;
38198         parentRels = parentRels || this._parentRels;
38199
38200         var type = entity && entity.type || oldentity && oldentity.type,
38201             removed, added, ways, rels, i;
38202
38203
38204         if (type === 'way') {
38205
38206             // Update parentWays
38207             if (oldentity && entity) {
38208                 removed = lodash.difference(oldentity.nodes, entity.nodes);
38209                 added = lodash.difference(entity.nodes, oldentity.nodes);
38210             } else if (oldentity) {
38211                 removed = oldentity.nodes;
38212                 added = [];
38213             } else if (entity) {
38214                 removed = [];
38215                 added = entity.nodes;
38216             }
38217             for (i = 0; i < removed.length; i++) {
38218                 parentWays[removed[i]] = lodash.without(parentWays[removed[i]], oldentity.id);
38219             }
38220             for (i = 0; i < added.length; i++) {
38221                 ways = lodash.without(parentWays[added[i]], entity.id);
38222                 ways.push(entity.id);
38223                 parentWays[added[i]] = ways;
38224             }
38225
38226         } else if (type === 'relation') {
38227
38228             // Update parentRels
38229             if (oldentity && entity) {
38230                 removed = lodash.difference(oldentity.members, entity.members);
38231                 added = lodash.difference(entity.members, oldentity);
38232             } else if (oldentity) {
38233                 removed = oldentity.members;
38234                 added = [];
38235             } else if (entity) {
38236                 removed = [];
38237                 added = entity.members;
38238             }
38239             for (i = 0; i < removed.length; i++) {
38240                 parentRels[removed[i].id] = lodash.without(parentRels[removed[i].id], oldentity.id);
38241             }
38242             for (i = 0; i < added.length; i++) {
38243                 rels = lodash.without(parentRels[added[i].id], entity.id);
38244                 rels.push(entity.id);
38245                 parentRels[added[i].id] = rels;
38246             }
38247         }
38248     },
38249
38250
38251     replace: function(entity) {
38252         if (this.entities[entity.id] === entity)
38253             return this;
38254
38255         return this.update(function() {
38256             this._updateCalculated(this.entities[entity.id], entity);
38257             this.entities[entity.id] = entity;
38258         });
38259     },
38260
38261
38262     remove: function(entity) {
38263         return this.update(function() {
38264             this._updateCalculated(entity, undefined);
38265             this.entities[entity.id] = undefined;
38266         });
38267     },
38268
38269
38270     revert: function(id) {
38271         var baseEntity = this.base().entities[id],
38272             headEntity = this.entities[id];
38273
38274         if (headEntity === baseEntity)
38275             return this;
38276
38277         return this.update(function() {
38278             this._updateCalculated(headEntity, baseEntity);
38279             delete this.entities[id];
38280         });
38281     },
38282
38283
38284     update: function() {
38285         var graph = this.frozen ? coreGraph$$1(this, true) : this;
38286
38287         for (var i = 0; i < arguments.length; i++) {
38288             arguments[i].call(graph, graph);
38289         }
38290
38291         if (this.frozen) graph.frozen = true;
38292
38293         return graph;
38294     },
38295
38296
38297     // Obliterates any existing entities
38298     load: function(entities) {
38299         var base = this.base();
38300         this.entities = Object.create(base.entities);
38301
38302         for (var i in entities) {
38303             this.entities[i] = entities[i];
38304             this._updateCalculated(base.entities[i], this.entities[i]);
38305         }
38306
38307         return this;
38308     }
38309 };
38310
38311 var index$9 = partialSort;
38312
38313 // Floyd-Rivest selection algorithm:
38314 // Rearrange items so that all items in the [left, k] range are smaller than all items in (k, right];
38315 // The k-th element will have the (k - left + 1)th smallest value in [left, right]
38316
38317 function partialSort(arr, k, left, right, compare) {
38318     left = left || 0;
38319     right = right || (arr.length - 1);
38320     compare = compare || defaultCompare;
38321
38322     while (right > left) {
38323         if (right - left > 600) {
38324             var n = right - left + 1;
38325             var m = k - left + 1;
38326             var z = Math.log(n);
38327             var s = 0.5 * Math.exp(2 * z / 3);
38328             var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1);
38329             var newLeft = Math.max(left, Math.floor(k - m * s / n + sd));
38330             var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd));
38331             partialSort(arr, k, newLeft, newRight, compare);
38332         }
38333
38334         var t = arr[k];
38335         var i = left;
38336         var j = right;
38337
38338         swap(arr, left, k);
38339         if (compare(arr[right], t) > 0) swap(arr, left, right);
38340
38341         while (i < j) {
38342             swap(arr, i, j);
38343             i++;
38344             j--;
38345             while (compare(arr[i], t) < 0) i++;
38346             while (compare(arr[j], t) > 0) j--;
38347         }
38348
38349         if (compare(arr[left], t) === 0) swap(arr, left, j);
38350         else {
38351             j++;
38352             swap(arr, j, right);
38353         }
38354
38355         if (j <= k) left = j + 1;
38356         if (k <= j) right = j - 1;
38357     }
38358 }
38359
38360 function swap(arr, i, j) {
38361     var tmp = arr[i];
38362     arr[i] = arr[j];
38363     arr[j] = tmp;
38364 }
38365
38366 function defaultCompare(a, b) {
38367     return a < b ? -1 : a > b ? 1 : 0;
38368 }
38369
38370 var index$8 = rbush;
38371
38372 var quickselect = index$9;
38373
38374 function rbush(maxEntries, format) {
38375     if (!(this instanceof rbush)) return new rbush(maxEntries, format);
38376
38377     // max entries in a node is 9 by default; min node fill is 40% for best performance
38378     this._maxEntries = Math.max(4, maxEntries || 9);
38379     this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4));
38380
38381     if (format) {
38382         this._initFormat(format);
38383     }
38384
38385     this.clear();
38386 }
38387
38388 rbush.prototype = {
38389
38390     all: function () {
38391         return this._all(this.data, []);
38392     },
38393
38394     search: function (bbox) {
38395
38396         var node = this.data,
38397             result = [],
38398             toBBox = this.toBBox;
38399
38400         if (!intersects$1(bbox, node)) return result;
38401
38402         var nodesToSearch = [],
38403             i, len, child, childBBox;
38404
38405         while (node) {
38406             for (i = 0, len = node.children.length; i < len; i++) {
38407
38408                 child = node.children[i];
38409                 childBBox = node.leaf ? toBBox(child) : child;
38410
38411                 if (intersects$1(bbox, childBBox)) {
38412                     if (node.leaf) result.push(child);
38413                     else if (contains$1(bbox, childBBox)) this._all(child, result);
38414                     else nodesToSearch.push(child);
38415                 }
38416             }
38417             node = nodesToSearch.pop();
38418         }
38419
38420         return result;
38421     },
38422
38423     collides: function (bbox) {
38424
38425         var node = this.data,
38426             toBBox = this.toBBox;
38427
38428         if (!intersects$1(bbox, node)) return false;
38429
38430         var nodesToSearch = [],
38431             i, len, child, childBBox;
38432
38433         while (node) {
38434             for (i = 0, len = node.children.length; i < len; i++) {
38435
38436                 child = node.children[i];
38437                 childBBox = node.leaf ? toBBox(child) : child;
38438
38439                 if (intersects$1(bbox, childBBox)) {
38440                     if (node.leaf || contains$1(bbox, childBBox)) return true;
38441                     nodesToSearch.push(child);
38442                 }
38443             }
38444             node = nodesToSearch.pop();
38445         }
38446
38447         return false;
38448     },
38449
38450     load: function (data) {
38451         if (!(data && data.length)) return this;
38452
38453         if (data.length < this._minEntries) {
38454             for (var i = 0, len = data.length; i < len; i++) {
38455                 this.insert(data[i]);
38456             }
38457             return this;
38458         }
38459
38460         // recursively build the tree with the given data from stratch using OMT algorithm
38461         var node = this._build(data.slice(), 0, data.length - 1, 0);
38462
38463         if (!this.data.children.length) {
38464             // save as is if tree is empty
38465             this.data = node;
38466
38467         } else if (this.data.height === node.height) {
38468             // split root if trees have the same height
38469             this._splitRoot(this.data, node);
38470
38471         } else {
38472             if (this.data.height < node.height) {
38473                 // swap trees if inserted one is bigger
38474                 var tmpNode = this.data;
38475                 this.data = node;
38476                 node = tmpNode;
38477             }
38478
38479             // insert the small tree into the large tree at appropriate level
38480             this._insert(node, this.data.height - node.height - 1, true);
38481         }
38482
38483         return this;
38484     },
38485
38486     insert: function (item) {
38487         if (item) this._insert(item, this.data.height - 1);
38488         return this;
38489     },
38490
38491     clear: function () {
38492         this.data = createNode([]);
38493         return this;
38494     },
38495
38496     remove: function (item, equalsFn) {
38497         if (!item) return this;
38498
38499         var node = this.data,
38500             bbox = this.toBBox(item),
38501             path = [],
38502             indexes = [],
38503             i, parent, index, goingUp;
38504
38505         // depth-first iterative tree traversal
38506         while (node || path.length) {
38507
38508             if (!node) { // go up
38509                 node = path.pop();
38510                 parent = path[path.length - 1];
38511                 i = indexes.pop();
38512                 goingUp = true;
38513             }
38514
38515             if (node.leaf) { // check current node
38516                 index = findItem(item, node.children, equalsFn);
38517
38518                 if (index !== -1) {
38519                     // item found, remove the item and condense tree upwards
38520                     node.children.splice(index, 1);
38521                     path.push(node);
38522                     this._condense(path);
38523                     return this;
38524                 }
38525             }
38526
38527             if (!goingUp && !node.leaf && contains$1(node, bbox)) { // go down
38528                 path.push(node);
38529                 indexes.push(i);
38530                 i = 0;
38531                 parent = node;
38532                 node = node.children[0];
38533
38534             } else if (parent) { // go right
38535                 i++;
38536                 node = parent.children[i];
38537                 goingUp = false;
38538
38539             } else node = null; // nothing found
38540         }
38541
38542         return this;
38543     },
38544
38545     toBBox: function (item) { return item; },
38546
38547     compareMinX: compareNodeMinX,
38548     compareMinY: compareNodeMinY,
38549
38550     toJSON: function () { return this.data; },
38551
38552     fromJSON: function (data) {
38553         this.data = data;
38554         return this;
38555     },
38556
38557     _all: function (node, result) {
38558         var nodesToSearch = [];
38559         while (node) {
38560             if (node.leaf) result.push.apply(result, node.children);
38561             else nodesToSearch.push.apply(nodesToSearch, node.children);
38562
38563             node = nodesToSearch.pop();
38564         }
38565         return result;
38566     },
38567
38568     _build: function (items, left, right, height) {
38569
38570         var N = right - left + 1,
38571             M = this._maxEntries,
38572             node;
38573
38574         if (N <= M) {
38575             // reached leaf level; return leaf
38576             node = createNode(items.slice(left, right + 1));
38577             calcBBox(node, this.toBBox);
38578             return node;
38579         }
38580
38581         if (!height) {
38582             // target height of the bulk-loaded tree
38583             height = Math.ceil(Math.log(N) / Math.log(M));
38584
38585             // target number of root entries to maximize storage utilization
38586             M = Math.ceil(N / Math.pow(M, height - 1));
38587         }
38588
38589         node = createNode([]);
38590         node.leaf = false;
38591         node.height = height;
38592
38593         // split the items into M mostly square tiles
38594
38595         var N2 = Math.ceil(N / M),
38596             N1 = N2 * Math.ceil(Math.sqrt(M)),
38597             i, j, right2, right3;
38598
38599         multiSelect(items, left, right, N1, this.compareMinX);
38600
38601         for (i = left; i <= right; i += N1) {
38602
38603             right2 = Math.min(i + N1 - 1, right);
38604
38605             multiSelect(items, i, right2, N2, this.compareMinY);
38606
38607             for (j = i; j <= right2; j += N2) {
38608
38609                 right3 = Math.min(j + N2 - 1, right2);
38610
38611                 // pack each entry recursively
38612                 node.children.push(this._build(items, j, right3, height - 1));
38613             }
38614         }
38615
38616         calcBBox(node, this.toBBox);
38617
38618         return node;
38619     },
38620
38621     _chooseSubtree: function (bbox, node, level, path) {
38622
38623         var i, len, child, targetNode, area, enlargement, minArea, minEnlargement;
38624
38625         while (true) {
38626             path.push(node);
38627
38628             if (node.leaf || path.length - 1 === level) break;
38629
38630             minArea = minEnlargement = Infinity;
38631
38632             for (i = 0, len = node.children.length; i < len; i++) {
38633                 child = node.children[i];
38634                 area = bboxArea(child);
38635                 enlargement = enlargedArea(bbox, child) - area;
38636
38637                 // choose entry with the least area enlargement
38638                 if (enlargement < minEnlargement) {
38639                     minEnlargement = enlargement;
38640                     minArea = area < minArea ? area : minArea;
38641                     targetNode = child;
38642
38643                 } else if (enlargement === minEnlargement) {
38644                     // otherwise choose one with the smallest area
38645                     if (area < minArea) {
38646                         minArea = area;
38647                         targetNode = child;
38648                     }
38649                 }
38650             }
38651
38652             node = targetNode || node.children[0];
38653         }
38654
38655         return node;
38656     },
38657
38658     _insert: function (item, level, isNode) {
38659
38660         var toBBox = this.toBBox,
38661             bbox = isNode ? item : toBBox(item),
38662             insertPath = [];
38663
38664         // find the best node for accommodating the item, saving all nodes along the path too
38665         var node = this._chooseSubtree(bbox, this.data, level, insertPath);
38666
38667         // put the item into the node
38668         node.children.push(item);
38669         extend$1(node, bbox);
38670
38671         // split on node overflow; propagate upwards if necessary
38672         while (level >= 0) {
38673             if (insertPath[level].children.length > this._maxEntries) {
38674                 this._split(insertPath, level);
38675                 level--;
38676             } else break;
38677         }
38678
38679         // adjust bboxes along the insertion path
38680         this._adjustParentBBoxes(bbox, insertPath, level);
38681     },
38682
38683     // split overflowed node into two
38684     _split: function (insertPath, level) {
38685
38686         var node = insertPath[level],
38687             M = node.children.length,
38688             m = this._minEntries;
38689
38690         this._chooseSplitAxis(node, m, M);
38691
38692         var splitIndex = this._chooseSplitIndex(node, m, M);
38693
38694         var newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex));
38695         newNode.height = node.height;
38696         newNode.leaf = node.leaf;
38697
38698         calcBBox(node, this.toBBox);
38699         calcBBox(newNode, this.toBBox);
38700
38701         if (level) insertPath[level - 1].children.push(newNode);
38702         else this._splitRoot(node, newNode);
38703     },
38704
38705     _splitRoot: function (node, newNode) {
38706         // split root node
38707         this.data = createNode([node, newNode]);
38708         this.data.height = node.height + 1;
38709         this.data.leaf = false;
38710         calcBBox(this.data, this.toBBox);
38711     },
38712
38713     _chooseSplitIndex: function (node, m, M) {
38714
38715         var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index;
38716
38717         minOverlap = minArea = Infinity;
38718
38719         for (i = m; i <= M - m; i++) {
38720             bbox1 = distBBox(node, 0, i, this.toBBox);
38721             bbox2 = distBBox(node, i, M, this.toBBox);
38722
38723             overlap = intersectionArea(bbox1, bbox2);
38724             area = bboxArea(bbox1) + bboxArea(bbox2);
38725
38726             // choose distribution with minimum overlap
38727             if (overlap < minOverlap) {
38728                 minOverlap = overlap;
38729                 index = i;
38730
38731                 minArea = area < minArea ? area : minArea;
38732
38733             } else if (overlap === minOverlap) {
38734                 // otherwise choose distribution with minimum area
38735                 if (area < minArea) {
38736                     minArea = area;
38737                     index = i;
38738                 }
38739             }
38740         }
38741
38742         return index;
38743     },
38744
38745     // sorts node children by the best axis for split
38746     _chooseSplitAxis: function (node, m, M) {
38747
38748         var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX,
38749             compareMinY = node.leaf ? this.compareMinY : compareNodeMinY,
38750             xMargin = this._allDistMargin(node, m, M, compareMinX),
38751             yMargin = this._allDistMargin(node, m, M, compareMinY);
38752
38753         // if total distributions margin value is minimal for x, sort by minX,
38754         // otherwise it's already sorted by minY
38755         if (xMargin < yMargin) node.children.sort(compareMinX);
38756     },
38757
38758     // total margin of all possible split distributions where each node is at least m full
38759     _allDistMargin: function (node, m, M, compare) {
38760
38761         node.children.sort(compare);
38762
38763         var toBBox = this.toBBox,
38764             leftBBox = distBBox(node, 0, m, toBBox),
38765             rightBBox = distBBox(node, M - m, M, toBBox),
38766             margin = bboxMargin(leftBBox) + bboxMargin(rightBBox),
38767             i, child;
38768
38769         for (i = m; i < M - m; i++) {
38770             child = node.children[i];
38771             extend$1(leftBBox, node.leaf ? toBBox(child) : child);
38772             margin += bboxMargin(leftBBox);
38773         }
38774
38775         for (i = M - m - 1; i >= m; i--) {
38776             child = node.children[i];
38777             extend$1(rightBBox, node.leaf ? toBBox(child) : child);
38778             margin += bboxMargin(rightBBox);
38779         }
38780
38781         return margin;
38782     },
38783
38784     _adjustParentBBoxes: function (bbox, path, level) {
38785         // adjust bboxes along the given tree path
38786         for (var i = level; i >= 0; i--) {
38787             extend$1(path[i], bbox);
38788         }
38789     },
38790
38791     _condense: function (path) {
38792         // go through the path, removing empty nodes and updating bboxes
38793         for (var i = path.length - 1, siblings; i >= 0; i--) {
38794             if (path[i].children.length === 0) {
38795                 if (i > 0) {
38796                     siblings = path[i - 1].children;
38797                     siblings.splice(siblings.indexOf(path[i]), 1);
38798
38799                 } else this.clear();
38800
38801             } else calcBBox(path[i], this.toBBox);
38802         }
38803     },
38804
38805     _initFormat: function (format) {
38806         // data format (minX, minY, maxX, maxY accessors)
38807
38808         // uses eval-type function compilation instead of just accepting a toBBox function
38809         // because the algorithms are very sensitive to sorting functions performance,
38810         // so they should be dead simple and without inner calls
38811
38812         var compareArr = ['return a', ' - b', ';'];
38813
38814         this.compareMinX = new Function('a', 'b', compareArr.join(format[0]));
38815         this.compareMinY = new Function('a', 'b', compareArr.join(format[1]));
38816
38817         this.toBBox = new Function('a',
38818             'return {minX: a' + format[0] +
38819             ', minY: a' + format[1] +
38820             ', maxX: a' + format[2] +
38821             ', maxY: a' + format[3] + '};');
38822     }
38823 };
38824
38825 function findItem(item, items, equalsFn) {
38826     if (!equalsFn) return items.indexOf(item);
38827
38828     for (var i = 0; i < items.length; i++) {
38829         if (equalsFn(item, items[i])) return i;
38830     }
38831     return -1;
38832 }
38833
38834 // calculate node's bbox from bboxes of its children
38835 function calcBBox(node, toBBox) {
38836     distBBox(node, 0, node.children.length, toBBox, node);
38837 }
38838
38839 // min bounding rectangle of node children from k to p-1
38840 function distBBox(node, k, p, toBBox, destNode) {
38841     if (!destNode) destNode = createNode(null);
38842     destNode.minX = Infinity;
38843     destNode.minY = Infinity;
38844     destNode.maxX = -Infinity;
38845     destNode.maxY = -Infinity;
38846
38847     for (var i = k, child; i < p; i++) {
38848         child = node.children[i];
38849         extend$1(destNode, node.leaf ? toBBox(child) : child);
38850     }
38851
38852     return destNode;
38853 }
38854
38855 function extend$1(a, b) {
38856     a.minX = Math.min(a.minX, b.minX);
38857     a.minY = Math.min(a.minY, b.minY);
38858     a.maxX = Math.max(a.maxX, b.maxX);
38859     a.maxY = Math.max(a.maxY, b.maxY);
38860     return a;
38861 }
38862
38863 function compareNodeMinX(a, b) { return a.minX - b.minX; }
38864 function compareNodeMinY(a, b) { return a.minY - b.minY; }
38865
38866 function bboxArea(a)   { return (a.maxX - a.minX) * (a.maxY - a.minY); }
38867 function bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); }
38868
38869 function enlargedArea(a, b) {
38870     return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) *
38871            (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY));
38872 }
38873
38874 function intersectionArea(a, b) {
38875     var minX = Math.max(a.minX, b.minX),
38876         minY = Math.max(a.minY, b.minY),
38877         maxX = Math.min(a.maxX, b.maxX),
38878         maxY = Math.min(a.maxY, b.maxY);
38879
38880     return Math.max(0, maxX - minX) *
38881            Math.max(0, maxY - minY);
38882 }
38883
38884 function contains$1(a, b) {
38885     return a.minX <= b.minX &&
38886            a.minY <= b.minY &&
38887            b.maxX <= a.maxX &&
38888            b.maxY <= a.maxY;
38889 }
38890
38891 function intersects$1(a, b) {
38892     return b.minX <= a.maxX &&
38893            b.minY <= a.maxY &&
38894            b.maxX >= a.minX &&
38895            b.maxY >= a.minY;
38896 }
38897
38898 function createNode(children) {
38899     return {
38900         children: children,
38901         height: 1,
38902         leaf: true,
38903         minX: Infinity,
38904         minY: Infinity,
38905         maxX: -Infinity,
38906         maxY: -Infinity
38907     };
38908 }
38909
38910 // sort an array so that items come in groups of n unsorted items, with groups sorted between each other;
38911 // combines selection algorithm with binary divide & conquer approach
38912
38913 function multiSelect(arr, left, right, n, compare) {
38914     var stack = [left, right],
38915         mid;
38916
38917     while (stack.length) {
38918         right = stack.pop();
38919         left = stack.pop();
38920
38921         if (right - left <= n) continue;
38922
38923         mid = left + Math.ceil((right - left) / n / 2) * n;
38924         quickselect(arr, mid, left, right, compare);
38925
38926         stack.push(left, mid, mid, right);
38927     }
38928 }
38929
38930 function coreTree(head) {
38931     var rtree = index$8(),
38932         bboxes = {},
38933         tree = {};
38934
38935
38936     function entityBBox(entity) {
38937         var bbox = entity.extent(head).bbox();
38938         bbox.id = entity.id;
38939         bboxes[entity.id] = bbox;
38940         return bbox;
38941     }
38942
38943
38944     function updateParents(entity, insertions, memo) {
38945         head.parentWays(entity).forEach(function(way) {
38946             if (bboxes[way.id]) {
38947                 rtree.remove(bboxes[way.id]);
38948                 insertions[way.id] = way;
38949             }
38950             updateParents(way, insertions, memo);
38951         });
38952
38953         head.parentRelations(entity).forEach(function(relation) {
38954             if (memo[entity.id]) return;
38955             memo[entity.id] = true;
38956             if (bboxes[relation.id]) {
38957                 rtree.remove(bboxes[relation.id]);
38958                 insertions[relation.id] = relation;
38959             }
38960             updateParents(relation, insertions, memo);
38961         });
38962     }
38963
38964
38965     tree.rebase = function(entities, force) {
38966         var insertions = {};
38967
38968         for (var i = 0; i < entities.length; i++) {
38969             var entity = entities[i];
38970
38971             if (!entity.visible)
38972                 continue;
38973
38974             if (head.entities.hasOwnProperty(entity.id) || bboxes[entity.id]) {
38975                 if (!force) {
38976                     continue;
38977                 } else if (bboxes[entity.id]) {
38978                     rtree.remove(bboxes[entity.id]);
38979                 }
38980             }
38981
38982             insertions[entity.id] = entity;
38983             updateParents(entity, insertions, {});
38984         }
38985
38986         rtree.load(lodash.map(insertions, entityBBox));
38987
38988         return tree;
38989     };
38990
38991
38992     tree.intersects = function(extent, graph) {
38993         if (graph !== head) {
38994             var diff = coreDifference(head, graph),
38995                 insertions = {};
38996
38997             head = graph;
38998
38999             diff.deleted().forEach(function(entity) {
39000                 rtree.remove(bboxes[entity.id]);
39001                 delete bboxes[entity.id];
39002             });
39003
39004             diff.modified().forEach(function(entity) {
39005                 rtree.remove(bboxes[entity.id]);
39006                 insertions[entity.id] = entity;
39007                 updateParents(entity, insertions, {});
39008             });
39009
39010             diff.created().forEach(function(entity) {
39011                 insertions[entity.id] = entity;
39012             });
39013
39014             rtree.load(lodash.map(insertions, entityBBox));
39015         }
39016
39017         return rtree.search(extent.bbox()).map(function(bbox) {
39018             return head.entity(bbox.id);
39019         });
39020     };
39021
39022
39023     return tree;
39024 }
39025
39026 /*
39027  * This code is licensed under the MIT license.
39028  *
39029  * Copyright © 2013, iD authors.
39030  *
39031  * Portions copyright © 2011, Keith Cirkel
39032  * See https://github.com/keithamus/jwerty
39033  *
39034  */
39035 function d3keybinding(namespace$$1) {
39036     var bindings = [];
39037
39038     function matches(binding, event$$1) {
39039         for (var p in binding.event) {
39040             if (event$$1[p] !== binding.event[p])
39041                 return false;
39042         }
39043         return true;
39044     }
39045
39046     function testBindings(isCapturing) {
39047         for (var i = 0; i < bindings.length; i++) {
39048             var binding = bindings[i];
39049
39050             if (!!binding.capture === isCapturing && matches(binding, event)) {
39051                 binding.callback();
39052             }
39053         }
39054     }
39055
39056     function capture() {
39057         testBindings(true);
39058     }
39059
39060     function bubble() {
39061         var tagName = select(event.target).node().tagName;
39062         if (tagName === 'INPUT' || tagName === 'SELECT' || tagName === 'TEXTAREA') {
39063             return;
39064         }
39065         testBindings(false);
39066     }
39067
39068     function keybinding(selection$$1) {
39069         selection$$1 = selection$$1 || select(document);
39070         selection$$1.on('keydown.capture' + namespace$$1, capture, true);
39071         selection$$1.on('keydown.bubble' + namespace$$1, bubble, false);
39072         return keybinding;
39073     }
39074
39075     keybinding.off = function(selection$$1) {
39076         bindings = [];
39077         selection$$1 = selection$$1 || select(document);
39078         selection$$1.on('keydown.capture' + namespace$$1, null);
39079         selection$$1.on('keydown.bubble' + namespace$$1, null);
39080         return keybinding;
39081     };
39082
39083     keybinding.on = function(codes, callback, capture) {
39084         var arr = [].concat(codes);
39085         for (var i = 0; i < arr.length; i++) {
39086             var code = arr[i];
39087             var binding = {
39088                 event: {
39089                     keyCode: 0,
39090                     shiftKey: false,
39091                     ctrlKey: false,
39092                     altKey: false,
39093                     metaKey: false
39094                 },
39095                 capture: capture,
39096                 callback: callback
39097             };
39098
39099             code = code.toLowerCase().match(/(?:(?:[^+⇧⌃⌥⌘])+|[⇧⌃⌥⌘]|\+\+|^\+$)/g);
39100
39101             for (var j = 0; j < code.length; j++) {
39102                 // Normalise matching errors
39103                 if (code[j] === '++') code[i] = '+';
39104
39105                 if (code[j] in d3keybinding.modifierCodes) {
39106                     binding.event[d3keybinding.modifierProperties[d3keybinding.modifierCodes[code[j]]]] = true;
39107                 } else if (code[j] in d3keybinding.keyCodes) {
39108                     binding.event.keyCode = d3keybinding.keyCodes[code[j]];
39109                 }
39110             }
39111
39112             bindings.push(binding);
39113         }
39114
39115         return keybinding;
39116     };
39117
39118     return keybinding;
39119 }
39120
39121
39122 d3keybinding.modifierCodes = {
39123     // Shift key, ⇧
39124     '⇧': 16, shift: 16,
39125     // CTRL key, on Mac: ⌃
39126     '⌃': 17, ctrl: 17,
39127     // ALT key, on Mac: ⌥ (Alt)
39128     '⌥': 18, alt: 18, option: 18,
39129     // META, on Mac: ⌘ (CMD), on Windows (Win), on Linux (Super)
39130     '⌘': 91, meta: 91, cmd: 91, 'super': 91, win: 91
39131 };
39132
39133 d3keybinding.modifierProperties = {
39134     16: 'shiftKey',
39135     17: 'ctrlKey',
39136     18: 'altKey',
39137     91: 'metaKey'
39138 };
39139
39140 d3keybinding.keyCodes = {
39141     // Backspace key, on Mac: ⌫ (Backspace)
39142     '⌫': 8, backspace: 8,
39143     // Tab Key, on Mac: ⇥ (Tab), on Windows ⇥⇥
39144     '⇥': 9, '⇆': 9, tab: 9,
39145     // Return key, ↩
39146     '↩': 13, 'return': 13, enter: 13, '⌅': 13,
39147     // Pause/Break key
39148     'pause': 19, 'pause-break': 19,
39149     // Caps Lock key, ⇪
39150     '⇪': 20, caps: 20, 'caps-lock': 20,
39151     // Escape key, on Mac: ⎋, on Windows: Esc
39152     '⎋': 27, escape: 27, esc: 27,
39153     // Space key
39154     space: 32,
39155     // Page-Up key, or pgup, on Mac: ↖
39156     '↖': 33, pgup: 33, 'page-up': 33,
39157     // Page-Down key, or pgdown, on Mac: ↘
39158     '↘': 34, pgdown: 34, 'page-down': 34,
39159     // END key, on Mac: ⇟
39160     '⇟': 35, end: 35,
39161     // HOME key, on Mac: ⇞
39162     '⇞': 36, home: 36,
39163     // Insert key, or ins
39164     ins: 45, insert: 45,
39165     // Delete key, on Mac: ⌦ (Delete)
39166     '⌦': 46, del: 46, 'delete': 46,
39167     // Left Arrow Key, or ←
39168     '←': 37, left: 37, 'arrow-left': 37,
39169     // Up Arrow Key, or ↑
39170     '↑': 38, up: 38, 'arrow-up': 38,
39171     // Right Arrow Key, or →
39172     '→': 39, right: 39, 'arrow-right': 39,
39173     // Up Arrow Key, or ↓
39174     '↓': 40, down: 40, 'arrow-down': 40,
39175     // odities, printing characters that come out wrong:
39176     // Firefox Equals
39177     'ffequals': 61,
39178     // Num-Multiply, or *
39179     '*': 106, star: 106, asterisk: 106, multiply: 106,
39180     // Num-Plus or +
39181     '+': 107, 'plus': 107,
39182     // Num-Subtract, or -
39183     '-': 109, subtract: 109,
39184     // Firefox Plus
39185     'ffplus': 171,
39186     // Firefox Minus
39187     'ffminus': 173,
39188     // Semicolon
39189     ';': 186, semicolon: 186,
39190     // = or equals
39191     '=': 187, 'equals': 187,
39192     // Comma, or ,
39193     ',': 188, comma: 188,
39194     // Dash / Underscore key
39195     'dash': 189,
39196     // Period, or ., or full-stop
39197     '.': 190, period: 190, 'full-stop': 190,
39198     // Slash, or /, or forward-slash
39199     '/': 191, slash: 191, 'forward-slash': 191,
39200     // Tick, or `, or back-quote
39201     '`': 192, tick: 192, 'back-quote': 192,
39202     // Open bracket, or [
39203     '[': 219, 'open-bracket': 219,
39204     // Back slash, or \
39205     '\\': 220, 'back-slash': 220,
39206     // Close backet, or ]
39207     ']': 221, 'close-bracket': 221,
39208     // Apostrophe, or Quote, or '
39209     '\'': 222, quote: 222, apostrophe: 222
39210 };
39211
39212 // NUMPAD 0-9
39213 var i$1 = 95;
39214 var n = 0;
39215 while (++i$1 < 106) {
39216     d3keybinding.keyCodes['num-' + n] = i$1;
39217     ++n;
39218 }
39219
39220 // 0-9
39221 i$1 = 47; n = 0;
39222 while (++i$1 < 58) {
39223     d3keybinding.keyCodes[n] = i$1;
39224     ++n;
39225 }
39226
39227 // F1-F25
39228 i$1 = 111; n = 1;
39229 while (++i$1 < 136) {
39230     d3keybinding.keyCodes['f' + n] = i$1;
39231     ++n;
39232 }
39233
39234 // a-z
39235 i$1 = 64;
39236 while (++i$1 < 91) {
39237     d3keybinding.keyCodes[String.fromCharCode(i$1).toLowerCase()] = i$1;
39238 }
39239
39240 function tooltip() {
39241   var tooltip = function(selection$$1) {
39242       selection$$1.each(setup);
39243     },
39244     animation = utilFunctor(false),
39245     html$$1 = utilFunctor(false),
39246     title = function() {
39247       var title = this.getAttribute('data-original-title');
39248       if (title) {
39249         return title;
39250       } else {
39251         title = this.getAttribute('title');
39252         this.removeAttribute('title');
39253         this.setAttribute('data-original-title', title);
39254       }
39255       return title;
39256     },
39257     over = 'mouseenter.tooltip',
39258     out = 'mouseleave.tooltip',
39259     placement = utilFunctor('top');
39260
39261
39262   tooltip.title = function(_) {
39263     if (arguments.length) {
39264       title = utilFunctor(_);
39265       return tooltip;
39266     } else {
39267       return title;
39268     }
39269   };
39270
39271
39272   tooltip.html = function(_) {
39273     if (arguments.length) {
39274       html$$1 = utilFunctor(_);
39275       return tooltip;
39276     } else {
39277       return html$$1;
39278     }
39279   };
39280
39281
39282   tooltip.placement = function(_) {
39283     if (arguments.length) {
39284       placement = utilFunctor(_);
39285       return tooltip;
39286     } else {
39287       return placement;
39288     }
39289   };
39290
39291
39292   tooltip.show = function(selection$$1) {
39293     selection$$1.each(show);
39294   };
39295
39296
39297   tooltip.hide = function(selection$$1) {
39298     selection$$1.each(hide);
39299   };
39300
39301
39302   tooltip.toggle = function(selection$$1) {
39303     selection$$1.each(toggle);
39304   };
39305
39306
39307   tooltip.destroy = function(selection$$1) {
39308     selection$$1
39309       .on(over, null)
39310       .on(out, null)
39311       .attr('title', function() {
39312         return this.getAttribute('data-original-title') || this.getAttribute('title');
39313       })
39314       .attr('data-original-title', null)
39315       .selectAll('.tooltip')
39316       .remove();
39317   };
39318
39319
39320   function setup() {
39321     var root = select(this),
39322         animate = animation.apply(this, arguments),
39323         tip = root.selectAll('.tooltip').data([0]);
39324
39325     var enter = tip.enter()
39326       .append('div')
39327       .attr('class', 'tooltip');
39328
39329     enter
39330       .append('div')
39331       .attr('class', 'tooltip-arrow');
39332
39333     enter
39334       .append('div')
39335       .attr('class', 'tooltip-inner');
39336
39337     tip = enter
39338       .merge(tip);
39339
39340     if (animate) {
39341       tip.classed('fade', true);
39342     }
39343
39344     var place = placement.apply(this, arguments);
39345     tip.classed(place, true);
39346
39347     root.on(over, show);
39348     root.on(out, hide);
39349   }
39350
39351
39352   function show() {
39353     var root = select(this),
39354       content = title.apply(this, arguments),
39355       tip = root.selectAll('.tooltip')
39356         .classed('in', true),
39357       markup = html$$1.apply(this, arguments);
39358
39359     tip.selectAll('.tooltip-inner')[markup ? 'html' : 'text'](content);
39360     var place = placement.apply(this, arguments),
39361       outer = getPosition(root.node()),
39362       inner = getPosition(tip.node()),
39363       pos;
39364
39365     switch (place) {
39366       case 'top':
39367         pos = {x: outer.x + (outer.w - inner.w) / 2, y: outer.y - inner.h};
39368         break;
39369       case 'right':
39370         pos = {x: outer.x + outer.w, y: outer.y + (outer.h - inner.h) / 2};
39371         break;
39372       case 'left':
39373         pos = {x: outer.x - inner.w, y: outer.y + (outer.h - inner.h) / 2};
39374         break;
39375       case 'bottom':
39376         pos = {x: Math.max(0, outer.x + (outer.w - inner.w) / 2), y: outer.y + outer.h};
39377         break;
39378     }
39379
39380     if (pos) {
39381       tip.style('left', ~~pos.x + 'px').style('top', ~~pos.y + 'px');
39382     } else {
39383       tip.style('left', null).style('top', null);
39384     }
39385
39386     this.tooltipVisible = true;
39387   }
39388
39389
39390   function hide() {
39391     select(this).selectAll('.tooltip')
39392       .classed('in', false);
39393
39394     this.tooltipVisible = false;
39395   }
39396
39397
39398   function toggle() {
39399     if (this.tooltipVisible) {
39400       hide.apply(this, arguments);
39401     } else {
39402       show.apply(this, arguments);
39403     }
39404   }
39405
39406   return tooltip;
39407 }
39408
39409
39410 function getPosition(node) {
39411   var mode = select(node).style('position');
39412   if (mode === 'absolute' || mode === 'static') {
39413     return {
39414       x: node.offsetLeft,
39415       y: node.offsetTop,
39416       w: node.offsetWidth,
39417       h: node.offsetHeight
39418     };
39419   } else {
39420     return {
39421       x: 0,
39422       y: 0,
39423       w: node.offsetWidth,
39424       h: node.offsetHeight
39425     };
39426   }
39427 }
39428
39429 function svgAreas$$1(projection, context) {
39430     // Patterns only work in Firefox when set directly on element.
39431     // (This is not a bug: https://bugzilla.mozilla.org/show_bug.cgi?id=750632)
39432     var patterns = {
39433         wetland: 'wetland',
39434         beach: 'beach',
39435         scrub: 'scrub',
39436         construction: 'construction',
39437         military: 'construction',
39438         cemetery: 'cemetery',
39439         grave_yard: 'cemetery',
39440         meadow: 'meadow',
39441         farm: 'farmland',
39442         farmland: 'farmland',
39443         orchard: 'orchard'
39444     };
39445
39446     var patternKeys = ['landuse', 'natural', 'amenity'];
39447
39448
39449     function setPattern(d) {
39450         for (var i = 0; i < patternKeys.length; i++) {
39451             if (patterns.hasOwnProperty(d.tags[patternKeys[i]])) {
39452                 this.style.fill = this.style.stroke = 'url("#pattern-' + patterns[d.tags[patternKeys[i]]] + '")';
39453                 return;
39454             }
39455         }
39456         this.style.fill = this.style.stroke = '';
39457     }
39458
39459
39460     return function drawAreas(selection$$1, graph, entities, filter) {
39461         var path$$1 = svgPath(projection, graph, true),
39462             areas = {},
39463             multipolygon;
39464
39465         for (var i = 0; i < entities.length; i++) {
39466             var entity = entities[i];
39467             if (entity.geometry(graph) !== 'area') continue;
39468
39469             multipolygon = osmIsSimpleMultipolygonOuterMember(entity, graph);
39470             if (multipolygon) {
39471                 areas[multipolygon.id] = {
39472                     entity: multipolygon.mergeTags(entity.tags),
39473                     area: Math.abs(entity.area(graph))
39474                 };
39475             } else if (!areas[entity.id]) {
39476                 areas[entity.id] = {
39477                     entity: entity,
39478                     area: Math.abs(entity.area(graph))
39479                 };
39480             }
39481         }
39482
39483         areas = values(areas).filter(function hasPath(a) { return path$$1(a.entity); });
39484         areas.sort(function areaSort(a, b) { return b.area - a.area; });
39485         areas = lodash.map(areas, 'entity');
39486
39487         var strokes = areas.filter(function(area$$1) {
39488             return area$$1.type === 'way';
39489         });
39490
39491         var data = {
39492             clip: areas,
39493             shadow: strokes,
39494             stroke: strokes,
39495             fill: areas
39496         };
39497
39498         var clipPaths = context.surface().selectAll('defs').selectAll('.clipPath')
39499            .filter(filter)
39500            .data(data.clip, osmEntity$$1.key);
39501
39502         clipPaths.exit()
39503            .remove();
39504
39505         var clipPathsEnter = clipPaths.enter()
39506            .append('clipPath')
39507            .attr('class', 'clipPath')
39508            .attr('id', function(entity) { return entity.id + '-clippath'; });
39509
39510         clipPathsEnter
39511            .append('path');
39512
39513         clipPaths.merge(clipPathsEnter)
39514            .selectAll('path')
39515            .attr('d', path$$1);
39516
39517
39518         var layer = selection$$1.selectAll('.layer-areas');
39519
39520         var areagroup = layer
39521             .selectAll('g.areagroup')
39522             .data(['fill', 'shadow', 'stroke']);
39523
39524         areagroup = areagroup.enter()
39525             .append('g')
39526             .attr('class', function(d) { return 'areagroup area-' + d; })
39527             .merge(areagroup);
39528
39529         var paths = areagroup
39530             .selectAll('path')
39531             .filter(filter)
39532             .data(function(layer) { return data[layer]; }, osmEntity$$1.key);
39533
39534         paths.exit()
39535             .remove();
39536
39537         var fills = selection$$1.selectAll('.area-fill path.area').nodes();
39538
39539         var bisect$$1 = bisector(function(node) {
39540             return -node.__data__.area(graph);
39541         }).left;
39542
39543         function sortedByArea(entity) {
39544             if (this._parent.__data__ === 'fill') {
39545                 return fills[bisect$$1(fills, -entity.area(graph))];
39546             }
39547         }
39548
39549         paths = paths.enter()
39550             .insert('path', sortedByArea)
39551             .merge(paths)
39552             .each(function(entity) {
39553                 var layer = this.parentNode.__data__;
39554
39555                 this.setAttribute('class', entity.type + ' area ' + layer + ' ' + entity.id);
39556
39557                 if (layer === 'fill') {
39558                     this.setAttribute('clip-path', 'url(#' + entity.id + '-clippath)');
39559                     setPattern.apply(this, arguments);
39560                 }
39561             })
39562             .call(svgTagClasses())
39563             .attr('d', path$$1);
39564     };
39565 }
39566
39567 function svgDebug(projection, context) {
39568
39569     function multipolygons(imagery) {
39570         return imagery.map(function(data$$1) {
39571             return {
39572                 type: 'MultiPolygon',
39573                 coordinates: [ data$$1.polygon ]
39574             };
39575         });
39576     }
39577
39578     function drawDebug(selection$$1) {
39579         var showsTile = context.getDebug('tile'),
39580             showsCollision = context.getDebug('collision'),
39581             showsImagery = context.getDebug('imagery'),
39582             showsImperial = context.getDebug('imperial'),
39583             showsDriveLeft = context.getDebug('driveLeft'),
39584             path$$1 = index$5(projection);
39585
39586
39587         var debugData = [];
39588         if (showsTile) {
39589             debugData.push({ class: 'red', label: 'tile' });
39590         }
39591         if (showsCollision) {
39592             debugData.push({ class: 'yellow', label: 'collision' });
39593         }
39594         if (showsImagery) {
39595             debugData.push({ class: 'orange', label: 'imagery' });
39596         }
39597         if (showsImperial) {
39598             debugData.push({ class: 'cyan', label: 'imperial' });
39599         }
39600         if (showsDriveLeft) {
39601             debugData.push({ class: 'green', label: 'driveLeft' });
39602         }
39603
39604
39605         var legend = select('#content')
39606             .selectAll('.debug-legend')
39607             .data(debugData.length ? [0] : []);
39608
39609         legend.exit()
39610             .remove();
39611
39612         legend = legend.enter()
39613             .append('div')
39614             .attr('class', 'fillD debug-legend')
39615             .merge(legend);
39616
39617
39618         var legendItems = legend.selectAll('.debug-legend-item')
39619             .data(debugData, function(d) { return d.label; });
39620
39621         legendItems.exit()
39622             .remove();
39623
39624         legendItems.enter()
39625             .append('span')
39626             .attr('class', function(d) { return 'debug-legend-item ' + d.class; })
39627             .text(function(d) { return d.label; });
39628
39629
39630         var layer = selection$$1.selectAll('.layer-debug')
39631             .data(showsImagery || showsImperial || showsDriveLeft ? [0] : []);
39632
39633         layer.exit()
39634             .remove();
39635
39636         layer = layer.enter()
39637             .append('g')
39638             .attr('class', 'layer-debug')
39639             .merge(layer);
39640
39641
39642         var extent$$1 = context.map().extent(),
39643             dataImagery = data.imagery || [],
39644             availableImagery = showsImagery && multipolygons(dataImagery.filter(function(source) {
39645                 if (!source.polygon) return false;
39646                 return source.polygon.some(function(polygon) {
39647                     return geoPolygonIntersectsPolygon(polygon, extent$$1, true);
39648                 });
39649             }));
39650
39651         var imagery = layer.selectAll('path.debug-imagery')
39652             .data(showsImagery ? availableImagery : []);
39653
39654         imagery.exit()
39655             .remove();
39656
39657         imagery.enter()
39658             .append('path')
39659             .attr('class', 'debug-imagery debug orange');
39660
39661
39662         var imperial = layer
39663             .selectAll('path.debug-imperial')
39664             .data(showsImperial ? [dataImperial] : []);
39665
39666         imperial.exit()
39667             .remove();
39668
39669         imperial.enter()
39670             .append('path')
39671             .attr('class', 'debug-imperial debug cyan');
39672
39673
39674         var driveLeft = layer
39675             .selectAll('path.debug-drive-left')
39676             .data(showsDriveLeft ? [dataDriveLeft] : []);
39677
39678         driveLeft.exit()
39679             .remove();
39680
39681         driveLeft.enter()
39682             .append('path')
39683             .attr('class', 'debug-drive-left debug green');
39684
39685
39686         // update
39687         layer.selectAll('path')
39688             .attr('d', path$$1);
39689     }
39690
39691
39692     // This looks strange because `enabled` methods on other layers are
39693     // chainable getter/setters, and this one is just a getter.
39694     drawDebug.enabled = function() {
39695         if (!arguments.length) {
39696             return context.getDebug('tile') ||
39697                 context.getDebug('collision') ||
39698                 context.getDebug('imagery') ||
39699                 context.getDebug('imperial') ||
39700                 context.getDebug('driveLeft');
39701         } else {
39702             return this;
39703         }
39704     };
39705
39706
39707     return drawDebug;
39708 }
39709
39710 /*
39711     A standalone SVG element that contains only a `defs` sub-element. To be
39712     used once globally, since defs IDs must be unique within a document.
39713 */
39714 function svgDefs(context) {
39715
39716     function SVGSpriteDefinition(id, href) {
39717         return function(defs) {
39718             request(href)
39719                 .mimeType('image/svg+xml')
39720                 .response(function(xhr) { return xhr.responseXML; })
39721                 .get(function(err, svg) {
39722                     if (err) return;
39723                     defs.node().appendChild(
39724                         select(svg.documentElement).attr('id', id).node()
39725                     );
39726                 });
39727         };
39728     }
39729
39730
39731     return function drawDefs(selection$$1) {
39732         var defs = selection$$1.append('defs');
39733
39734         // marker
39735         defs.append('marker')
39736             .attr('id', 'oneway-marker')
39737             .attr('viewBox', '0 0 10 10')
39738             .attr('refY', 2.5)
39739             .attr('refX', 5)
39740             .attr('markerWidth', 2)
39741             .attr('markerHeight', 2)
39742             .attr('markerUnits', 'strokeWidth')
39743             .attr('orient', 'auto')
39744
39745             .append('path')
39746             .attr('class', 'oneway')
39747             .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')
39748             .attr('stroke', 'none')
39749             .attr('fill', '#000')
39750             .attr('opacity', '0.5');
39751
39752         // patterns
39753         var patterns = defs.selectAll('pattern')
39754             .data([
39755                 // pattern name, pattern image name
39756                 ['wetland', 'wetland'],
39757                 ['construction', 'construction'],
39758                 ['cemetery', 'cemetery'],
39759                 ['orchard', 'orchard'],
39760                 ['farmland', 'farmland'],
39761                 ['beach', 'dots'],
39762                 ['scrub', 'dots'],
39763                 ['meadow', 'dots']
39764             ])
39765             .enter()
39766             .append('pattern')
39767             .attr('id', function (d) {
39768                 return 'pattern-' + d[0];
39769             })
39770             .attr('width', 32)
39771             .attr('height', 32)
39772             .attr('patternUnits', 'userSpaceOnUse');
39773
39774         patterns.append('rect')
39775             .attr('x', 0)
39776             .attr('y', 0)
39777             .attr('width', 32)
39778             .attr('height', 32)
39779             .attr('class', function (d) {
39780                     return 'pattern-color-' + d[0];
39781             });
39782
39783         patterns.append('image')
39784             .attr('x', 0)
39785             .attr('y', 0)
39786             .attr('width', 32)
39787             .attr('height', 32)
39788             .attr('xlink:href', function (d) {
39789                 return context.imagePath('pattern/' + d[1] + '.png');
39790             });
39791
39792         // clip paths
39793         defs.selectAll()
39794             .data([12, 18, 20, 32, 45])
39795             .enter()
39796             .append('clipPath')
39797             .attr('id', function (d) {
39798                 return 'clip-square-' + d;
39799             })
39800             .append('rect')
39801             .attr('x', 0)
39802             .attr('y', 0)
39803             .attr('width', function (d) {
39804                 return d;
39805             })
39806             .attr('height', function (d) {
39807                 return d;
39808             });
39809
39810         defs.call(SVGSpriteDefinition(
39811             'iD-sprite',
39812             context.imagePath('iD-sprite.svg')));
39813
39814         defs.call(SVGSpriteDefinition(
39815             'maki-sprite',
39816             context.imagePath('maki-sprite.svg')));
39817     };
39818 }
39819
39820 var sax = createCommonjsModule(function (module, exports) {
39821 //[4]           NameStartChar      ::=          ":" | [A-Z] | "_" | [a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
39822 //[4a]          NameChar           ::=          NameStartChar | "-" | "." | [0-9] | #xB7 | [#x0300-#x036F] | [#x203F-#x2040]
39823 //[5]           Name       ::=          NameStartChar (NameChar)*
39824 var nameStartChar = /[A-Z_a-z\xC0-\xD6\xD8-\xF6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD]/;//\u10000-\uEFFFF
39825 var nameChar = new RegExp("[\\-\\.0-9"+nameStartChar.source.slice(1,-1)+"\u00B7\u0300-\u036F\\u203F-\u2040]");
39826 var tagNamePattern = new RegExp('^'+nameStartChar.source+nameChar.source+'*(?:\:'+nameStartChar.source+nameChar.source+'*)?$');
39827 //var tagNamePattern = /^[a-zA-Z_][\w\-\.]*(?:\:[a-zA-Z_][\w\-\.]*)?$/
39828 //var handlers = 'resolveEntity,getExternalSubset,characters,endDocument,endElement,endPrefixMapping,ignorableWhitespace,processingInstruction,setDocumentLocator,skippedEntity,startDocument,startElement,startPrefixMapping,notationDecl,unparsedEntityDecl,error,fatalError,warning,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,comment,endCDATA,endDTD,endEntity,startCDATA,startDTD,startEntity'.split(',')
39829
39830 //S_TAG,        S_ATTR, S_EQ,   S_V
39831 //S_ATTR_S,     S_E,    S_S,    S_C
39832 var S_TAG = 0;//tag name offerring
39833 var S_ATTR = 1;//attr name offerring 
39834 var S_ATTR_S=2;//attr name end and space offer
39835 var S_EQ = 3;//=space?
39836 var S_V = 4;//attr value(no quot value only)
39837 var S_E = 5;//attr value end and no space(quot end)
39838 var S_S = 6;//(attr value end || tag end ) && (space offer)
39839 var S_C = 7;//closed el<el />
39840
39841 function XMLReader(){
39842         
39843 }
39844
39845 XMLReader.prototype = {
39846         parse:function(source,defaultNSMap,entityMap){
39847                 var domBuilder = this.domBuilder;
39848                 domBuilder.startDocument();
39849                 _copy(defaultNSMap ,defaultNSMap = {});
39850                 parse(source,defaultNSMap,entityMap,
39851                                 domBuilder,this.errorHandler);
39852                 domBuilder.endDocument();
39853         }
39854 };
39855 function parse(source,defaultNSMapCopy,entityMap,domBuilder,errorHandler){
39856   function fixedFromCharCode(code) {
39857                 // String.prototype.fromCharCode does not supports
39858                 // > 2 bytes unicode chars directly
39859                 if (code > 0xffff) {
39860                         code -= 0x10000;
39861                         var surrogate1 = 0xd800 + (code >> 10)
39862                                 , surrogate2 = 0xdc00 + (code & 0x3ff);
39863
39864                         return String.fromCharCode(surrogate1, surrogate2);
39865                 } else {
39866                         return String.fromCharCode(code);
39867                 }
39868         }
39869         function entityReplacer(a){
39870                 var k = a.slice(1,-1);
39871                 if(k in entityMap){
39872                         return entityMap[k]; 
39873                 }else if(k.charAt(0) === '#'){
39874                         return fixedFromCharCode(parseInt(k.substr(1).replace('x','0x')))
39875                 }else{
39876                         errorHandler.error('entity not found:'+a);
39877                         return a;
39878                 }
39879         }
39880         function appendText(end){//has some bugs
39881                 if(end>start){
39882                         var xt = source.substring(start,end).replace(/&#?\w+;/g,entityReplacer);
39883                         locator&&position(start);
39884                         domBuilder.characters(xt,0,end-start);
39885                         start = end;
39886                 }
39887         }
39888         function position(p,m){
39889                 while(p>=lineEnd && (m = linePattern.exec(source))){
39890                         lineStart = m.index;
39891                         lineEnd = lineStart + m[0].length;
39892                         locator.lineNumber++;
39893                         //console.log('line++:',locator,startPos,endPos)
39894                 }
39895                 locator.columnNumber = p-lineStart+1;
39896         }
39897         var lineStart = 0;
39898         var lineEnd = 0;
39899         var linePattern = /.+(?:\r\n?|\n)|.*$/g;
39900         var locator = domBuilder.locator;
39901         
39902         var parseStack = [{currentNSMap:defaultNSMapCopy}];
39903         var closeMap = {};
39904         var start = 0;
39905         while(true){
39906                 try{
39907                         var tagStart = source.indexOf('<',start);
39908                         if(tagStart<0){
39909                                 if(!source.substr(start).match(/^\s*$/)){
39910                                         var doc = domBuilder.document;
39911                                 var text = doc.createTextNode(source.substr(start));
39912                                 doc.appendChild(text);
39913                                 domBuilder.currentElement = text;
39914                                 }
39915                                 return;
39916                         }
39917                         if(tagStart>start){
39918                                 appendText(tagStart);
39919                         }
39920                         switch(source.charAt(tagStart+1)){
39921                         case '/':
39922                                 var end = source.indexOf('>',tagStart+3);
39923                                 var tagName = source.substring(tagStart+2,end);
39924                                 var config = parseStack.pop();
39925                                 var localNSMap = config.localNSMap;
39926                         if(config.tagName != tagName){
39927                             errorHandler.fatalError("end tag name: "+tagName+' is not match the current start tagName:'+config.tagName );
39928                         }
39929                                 domBuilder.endElement(config.uri,config.localName,tagName);
39930                                 if(localNSMap){
39931                                         for(var prefix in localNSMap){
39932                                                 domBuilder.endPrefixMapping(prefix) ;
39933                                         }
39934                                 }
39935                                 end++;
39936                                 break;
39937                                 // end elment
39938                         case '?':// <?...?>
39939                                 locator&&position(tagStart);
39940                                 end = parseInstruction(source,tagStart,domBuilder);
39941                                 break;
39942                         case '!':// <!doctype,<![CDATA,<!--
39943                                 locator&&position(tagStart);
39944                                 end = parseDCC(source,tagStart,domBuilder,errorHandler);
39945                                 break;
39946                         default:
39947                         
39948                                 locator&&position(tagStart);
39949                                 
39950                                 var el = new ElementAttributes();
39951                                 
39952                                 //elStartEnd
39953                                 var end = parseElementStartPart(source,tagStart,el,entityReplacer,errorHandler);
39954                                 var len = el.length;
39955                                 
39956                                 if(locator){
39957                                         if(len){
39958                                                 //attribute position fixed
39959                                                 for(var i = 0;i<len;i++){
39960                                                         var a = el[i];
39961                                                         position(a.offset);
39962                                                         a.offset = copyLocator(locator,{});
39963                                                 }
39964                                         }
39965                                         position(end);
39966                                 }
39967                                 if(!el.closed && fixSelfClosed(source,end,el.tagName,closeMap)){
39968                                         el.closed = true;
39969                                         if(!entityMap.nbsp){
39970                                                 errorHandler.warning('unclosed xml attribute');
39971                                         }
39972                                 }
39973                                 appendElement(el,domBuilder,parseStack);
39974                                 
39975                                 
39976                                 if(el.uri === 'http://www.w3.org/1999/xhtml' && !el.closed){
39977                                         end = parseHtmlSpecialContent(source,end,el.tagName,entityReplacer,domBuilder);
39978                                 }else{
39979                                         end++;
39980                                 }
39981                         }
39982                 }catch(e){
39983                         errorHandler.error('element parse error: '+e);
39984                         end = -1;
39985                 }
39986                 if(end>start){
39987                         start = end;
39988                 }else{
39989                         //TODO: 这里有可能sax回退,有位置错误风险
39990                         appendText(Math.max(tagStart,start)+1);
39991                 }
39992         }
39993 }
39994 function copyLocator(f,t){
39995         t.lineNumber = f.lineNumber;
39996         t.columnNumber = f.columnNumber;
39997         return t;
39998 }
39999
40000 /**
40001  * @see #appendElement(source,elStartEnd,el,selfClosed,entityReplacer,domBuilder,parseStack);
40002  * @return end of the elementStartPart(end of elementEndPart for selfClosed el)
40003  */
40004 function parseElementStartPart(source,start,el,entityReplacer,errorHandler){
40005         var attrName;
40006         var value;
40007         var p = ++start;
40008         var s = S_TAG;//status
40009         while(true){
40010                 var c = source.charAt(p);
40011                 switch(c){
40012                 case '=':
40013                         if(s === S_ATTR){//attrName
40014                                 attrName = source.slice(start,p);
40015                                 s = S_EQ;
40016                         }else if(s === S_ATTR_S){
40017                                 s = S_EQ;
40018                         }else{
40019                                 //fatalError: equal must after attrName or space after attrName
40020                                 throw new Error('attribute equal must after attrName');
40021                         }
40022                         break;
40023                 case '\'':
40024                 case '"':
40025                         if(s === S_EQ){//equal
40026                                 start = p+1;
40027                                 p = source.indexOf(c,start);
40028                                 if(p>0){
40029                                         value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
40030                                         el.add(attrName,value,start-1);
40031                                         s = S_E;
40032                                 }else{
40033                                         //fatalError: no end quot match
40034                                         throw new Error('attribute value no end \''+c+'\' match');
40035                                 }
40036                         }else if(s == S_V){
40037                                 value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
40038                                 //console.log(attrName,value,start,p)
40039                                 el.add(attrName,value,start);
40040                                 //console.dir(el)
40041                                 errorHandler.warning('attribute "'+attrName+'" missed start quot('+c+')!!');
40042                                 start = p+1;
40043                                 s = S_E;
40044                         }else{
40045                                 //fatalError: no equal before
40046                                 throw new Error('attribute value must after "="');
40047                         }
40048                         break;
40049                 case '/':
40050                         switch(s){
40051                         case S_TAG:
40052                                 el.setTagName(source.slice(start,p));
40053                         case S_E:
40054                         case S_S:
40055                         case S_C:
40056                                 s = S_C;
40057                                 el.closed = true;
40058                         case S_V:
40059                         case S_ATTR:
40060                         case S_ATTR_S:
40061                                 break;
40062                         //case S_EQ:
40063                         default:
40064                                 throw new Error("attribute invalid close char('/')")
40065                         }
40066                         break;
40067                 case ''://end document
40068                         //throw new Error('unexpected end of input')
40069                         errorHandler.error('unexpected end of input');
40070                 case '>':
40071                         switch(s){
40072                         case S_TAG:
40073                                 el.setTagName(source.slice(start,p));
40074                         case S_E:
40075                         case S_S:
40076                         case S_C:
40077                                 break;//normal
40078                         case S_V://Compatible state
40079                         case S_ATTR:
40080                                 value = source.slice(start,p);
40081                                 if(value.slice(-1) === '/'){
40082                                         el.closed  = true;
40083                                         value = value.slice(0,-1);
40084                                 }
40085                         case S_ATTR_S:
40086                                 if(s === S_ATTR_S){
40087                                         value = attrName;
40088                                 }
40089                                 if(s == S_V){
40090                                         errorHandler.warning('attribute "'+value+'" missed quot(")!!');
40091                                         el.add(attrName,value.replace(/&#?\w+;/g,entityReplacer),start);
40092                                 }else{
40093                                         errorHandler.warning('attribute "'+value+'" missed value!! "'+value+'" instead!!');
40094                                         el.add(value,value,start);
40095                                 }
40096                                 break;
40097                         case S_EQ:
40098                                 throw new Error('attribute value missed!!');
40099                         }
40100 //                      console.log(tagName,tagNamePattern,tagNamePattern.test(tagName))
40101                         return p;
40102                 /*xml space '\x20' | #x9 | #xD | #xA; */
40103                 case '\u0080':
40104                         c = ' ';
40105                 default:
40106                         if(c<= ' '){//space
40107                                 switch(s){
40108                                 case S_TAG:
40109                                         el.setTagName(source.slice(start,p));//tagName
40110                                         s = S_S;
40111                                         break;
40112                                 case S_ATTR:
40113                                         attrName = source.slice(start,p);
40114                                         s = S_ATTR_S;
40115                                         break;
40116                                 case S_V:
40117                                         var value = source.slice(start,p).replace(/&#?\w+;/g,entityReplacer);
40118                                         errorHandler.warning('attribute "'+value+'" missed quot(")!!');
40119                                         el.add(attrName,value,start);
40120                                 case S_E:
40121                                         s = S_S;
40122                                         break;
40123                                 //case S_S:
40124                                 //case S_EQ:
40125                                 //case S_ATTR_S:
40126                                 //      void();break;
40127                                 //case S_C:
40128                                         //ignore warning
40129                                 }
40130                         }else{//not space
40131 //S_TAG,        S_ATTR, S_EQ,   S_V
40132 //S_ATTR_S,     S_E,    S_S,    S_C
40133                                 switch(s){
40134                                 //case S_TAG:void();break;
40135                                 //case S_ATTR:void();break;
40136                                 //case S_V:void();break;
40137                                 case S_ATTR_S:
40138                                         errorHandler.warning('attribute "'+attrName+'" missed value!! "'+attrName+'" instead!!');
40139                                         el.add(attrName,attrName,start);
40140                                         start = p;
40141                                         s = S_ATTR;
40142                                         break;
40143                                 case S_E:
40144                                         errorHandler.warning('attribute space is required"'+attrName+'"!!');
40145                                 case S_S:
40146                                         s = S_ATTR;
40147                                         start = p;
40148                                         break;
40149                                 case S_EQ:
40150                                         s = S_V;
40151                                         start = p;
40152                                         break;
40153                                 case S_C:
40154                                         throw new Error("elements closed character '/' and '>' must be connected to");
40155                                 }
40156                         }
40157                 }
40158                 p++;
40159         }
40160 }
40161 /**
40162  * @return end of the elementStartPart(end of elementEndPart for selfClosed el)
40163  */
40164 function appendElement(el,domBuilder,parseStack){
40165         var tagName = el.tagName;
40166         var localNSMap = null;
40167         var currentNSMap = parseStack[parseStack.length-1].currentNSMap;
40168         var i = el.length;
40169         while(i--){
40170                 var a = el[i];
40171                 var qName = a.qName;
40172                 var value = a.value;
40173                 var nsp = qName.indexOf(':');
40174                 if(nsp>0){
40175                         var prefix = a.prefix = qName.slice(0,nsp);
40176                         var localName = qName.slice(nsp+1);
40177                         var nsPrefix = prefix === 'xmlns' && localName;
40178                 }else{
40179                         localName = qName;
40180                         prefix = null;
40181                         nsPrefix = qName === 'xmlns' && '';
40182                 }
40183                 //can not set prefix,because prefix !== ''
40184                 a.localName = localName ;
40185                 //prefix == null for no ns prefix attribute 
40186                 if(nsPrefix !== false){//hack!!
40187                         if(localNSMap == null){
40188                                 localNSMap = {};
40189                                 //console.log(currentNSMap,0)
40190                                 _copy(currentNSMap,currentNSMap={});
40191                                 //console.log(currentNSMap,1)
40192                         }
40193                         currentNSMap[nsPrefix] = localNSMap[nsPrefix] = value;
40194                         a.uri = 'http://www.w3.org/2000/xmlns/';
40195                         domBuilder.startPrefixMapping(nsPrefix, value); 
40196                 }
40197         }
40198         var i = el.length;
40199         while(i--){
40200                 a = el[i];
40201                 var prefix = a.prefix;
40202                 if(prefix){//no prefix attribute has no namespace
40203                         if(prefix === 'xml'){
40204                                 a.uri = 'http://www.w3.org/XML/1998/namespace';
40205                         }if(prefix !== 'xmlns'){
40206                                 a.uri = currentNSMap[prefix];
40207                                 
40208                                 //{console.log('###'+a.qName,domBuilder.locator.systemId+'',currentNSMap,a.uri)}
40209                         }
40210                 }
40211         }
40212         var nsp = tagName.indexOf(':');
40213         if(nsp>0){
40214                 prefix = el.prefix = tagName.slice(0,nsp);
40215                 localName = el.localName = tagName.slice(nsp+1);
40216         }else{
40217                 prefix = null;//important!!
40218                 localName = el.localName = tagName;
40219         }
40220         //no prefix element has default namespace
40221         var ns = el.uri = currentNSMap[prefix || ''];
40222         domBuilder.startElement(ns,localName,tagName,el);
40223         //endPrefixMapping and startPrefixMapping have not any help for dom builder
40224         //localNSMap = null
40225         if(el.closed){
40226                 domBuilder.endElement(ns,localName,tagName);
40227                 if(localNSMap){
40228                         for(prefix in localNSMap){
40229                                 domBuilder.endPrefixMapping(prefix); 
40230                         }
40231                 }
40232         }else{
40233                 el.currentNSMap = currentNSMap;
40234                 el.localNSMap = localNSMap;
40235                 parseStack.push(el);
40236         }
40237 }
40238 function parseHtmlSpecialContent(source,elStartEnd,tagName,entityReplacer,domBuilder){
40239         if(/^(?:script|textarea)$/i.test(tagName)){
40240                 var elEndStart =  source.indexOf('</'+tagName+'>',elStartEnd);
40241                 var text = source.substring(elStartEnd+1,elEndStart);
40242                 if(/[&<]/.test(text)){
40243                         if(/^script$/i.test(tagName)){
40244                                 //if(!/\]\]>/.test(text)){
40245                                         //lexHandler.startCDATA();
40246                                         domBuilder.characters(text,0,text.length);
40247                                         //lexHandler.endCDATA();
40248                                         return elEndStart;
40249                                 //}
40250                         }//}else{//text area
40251                                 text = text.replace(/&#?\w+;/g,entityReplacer);
40252                                 domBuilder.characters(text,0,text.length);
40253                                 return elEndStart;
40254                         //}
40255                         
40256                 }
40257         }
40258         return elStartEnd+1;
40259 }
40260 function fixSelfClosed(source,elStartEnd,tagName,closeMap){
40261         //if(tagName in closeMap){
40262         var pos = closeMap[tagName];
40263         if(pos == null){
40264                 //console.log(tagName)
40265                 pos = closeMap[tagName] = source.lastIndexOf('</'+tagName+'>');
40266         }
40267         return pos<elStartEnd;
40268         //} 
40269 }
40270 function _copy(source,target){
40271         for(var n in source){target[n] = source[n];}
40272 }
40273 function parseDCC(source,start,domBuilder,errorHandler){//sure start with '<!'
40274         var next= source.charAt(start+2);
40275         switch(next){
40276         case '-':
40277                 if(source.charAt(start + 3) === '-'){
40278                         var end = source.indexOf('-->',start+4);
40279                         //append comment source.substring(4,end)//<!--
40280                         if(end>start){
40281                                 domBuilder.comment(source,start+4,end-start-4);
40282                                 return end+3;
40283                         }else{
40284                                 errorHandler.error("Unclosed comment");
40285                                 return -1;
40286                         }
40287                 }else{
40288                         //error
40289                         return -1;
40290                 }
40291         default:
40292                 if(source.substr(start+3,6) == 'CDATA['){
40293                         var end = source.indexOf(']]>',start+9);
40294                         domBuilder.startCDATA();
40295                         domBuilder.characters(source,start+9,end-start-9);
40296                         domBuilder.endCDATA(); 
40297                         return end+3;
40298                 }
40299                 //<!DOCTYPE
40300                 //startDTD(java.lang.String name, java.lang.String publicId, java.lang.String systemId) 
40301                 var matchs = split(source,start);
40302                 var len = matchs.length;
40303                 if(len>1 && /!doctype/i.test(matchs[0][0])){
40304                         var name = matchs[1][0];
40305                         var pubid = len>3 && /^public$/i.test(matchs[2][0]) && matchs[3][0];
40306                         var sysid = len>4 && matchs[4][0];
40307                         var lastMatch = matchs[len-1];
40308                         domBuilder.startDTD(name,pubid && pubid.replace(/^(['"])(.*?)\1$/,'$2'),
40309                                         sysid && sysid.replace(/^(['"])(.*?)\1$/,'$2'));
40310                         domBuilder.endDTD();
40311                         
40312                         return lastMatch.index+lastMatch[0].length
40313                 }
40314         }
40315         return -1;
40316 }
40317
40318
40319
40320 function parseInstruction(source,start,domBuilder){
40321         var end = source.indexOf('?>',start);
40322         if(end){
40323                 var match = source.substring(start,end).match(/^<\?(\S*)\s*([\s\S]*?)\s*$/);
40324                 if(match){
40325                         var len = match[0].length;
40326                         domBuilder.processingInstruction(match[1], match[2]) ;
40327                         return end+2;
40328                 }else{//error
40329                         return -1;
40330                 }
40331         }
40332         return -1;
40333 }
40334
40335 /**
40336  * @param source
40337  */
40338 function ElementAttributes(source){
40339         
40340 }
40341 ElementAttributes.prototype = {
40342         setTagName:function(tagName){
40343                 if(!tagNamePattern.test(tagName)){
40344                         throw new Error('invalid tagName:'+tagName)
40345                 }
40346                 this.tagName = tagName;
40347         },
40348         add:function(qName,value,offset){
40349                 if(!tagNamePattern.test(qName)){
40350                         throw new Error('invalid attribute:'+qName)
40351                 }
40352                 this[this.length++] = {qName:qName,value:value,offset:offset};
40353         },
40354         length:0,
40355         getLocalName:function(i){return this[i].localName},
40356         getOffset:function(i){return this[i].offset},
40357         getQName:function(i){return this[i].qName},
40358         getURI:function(i){return this[i].uri},
40359         getValue:function(i){return this[i].value}
40360 //      ,getIndex:function(uri, localName)){
40361 //              if(localName){
40362 //                      
40363 //              }else{
40364 //                      var qName = uri
40365 //              }
40366 //      },
40367 //      getValue:function(){return this.getValue(this.getIndex.apply(this,arguments))},
40368 //      getType:function(uri,localName){}
40369 //      getType:function(i){},
40370 };
40371
40372
40373
40374
40375 function _set_proto_(thiz,parent){
40376         thiz.__proto__ = parent;
40377         return thiz;
40378 }
40379 if(!(_set_proto_({},_set_proto_.prototype) instanceof _set_proto_)){
40380         _set_proto_ = function(thiz,parent){
40381                 function p(){}
40382                 p.prototype = parent;
40383                 p = new p();
40384                 for(parent in thiz){
40385                         p[parent] = thiz[parent];
40386                 }
40387                 return p;
40388         };
40389 }
40390
40391 function split(source,start){
40392         var match;
40393         var buf = [];
40394         var reg = /'[^']+'|"[^"]+"|[^\s<>\/=]+=?|(\/?\s*>|<)/g;
40395         reg.lastIndex = start;
40396         reg.exec(source);//skip <
40397         while(match = reg.exec(source)){
40398                 buf.push(match);
40399                 if(match[1])return buf;
40400         }
40401 }
40402
40403 if(typeof commonjsRequire == 'function'){
40404         exports.XMLReader = XMLReader;
40405 }
40406 });
40407
40408 var dom = createCommonjsModule(function (module, exports) {
40409 /*
40410  * DOM Level 2
40411  * Object DOMException
40412  * @see http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html
40413  * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/ecma-script-binding.html
40414  */
40415
40416 function copy(src,dest){
40417         for(var p in src){
40418                 dest[p] = src[p];
40419         }
40420 }
40421 /**
40422 ^\w+\.prototype\.([_\w]+)\s*=\s*((?:.*\{\s*?[\r\n][\s\S]*?^})|\S.*?(?=[;\r\n]));?
40423 ^\w+\.prototype\.([_\w]+)\s*=\s*(\S.*?(?=[;\r\n]));?
40424  */
40425 function _extends(Class,Super){
40426         var pt = Class.prototype;
40427         if(Object.create){
40428                 var ppt = Object.create(Super.prototype);
40429                 pt.__proto__ = ppt;
40430         }
40431         if(!(pt instanceof Super)){
40432                 function t(){}
40433                 t.prototype = Super.prototype;
40434                 t = new t();
40435                 copy(pt,t);
40436                 Class.prototype = pt = t;
40437         }
40438         if(pt.constructor != Class){
40439                 if(typeof Class != 'function'){
40440                         console.error("unknow Class:"+Class);
40441                 }
40442                 pt.constructor = Class;
40443         }
40444 }
40445 var htmlns = 'http://www.w3.org/1999/xhtml';
40446 // Node Types
40447 var NodeType = {};
40448 var ELEMENT_NODE                = NodeType.ELEMENT_NODE                = 1;
40449 var ATTRIBUTE_NODE              = NodeType.ATTRIBUTE_NODE              = 2;
40450 var TEXT_NODE                   = NodeType.TEXT_NODE                   = 3;
40451 var CDATA_SECTION_NODE          = NodeType.CDATA_SECTION_NODE          = 4;
40452 var ENTITY_REFERENCE_NODE       = NodeType.ENTITY_REFERENCE_NODE       = 5;
40453 var ENTITY_NODE                 = NodeType.ENTITY_NODE                 = 6;
40454 var PROCESSING_INSTRUCTION_NODE = NodeType.PROCESSING_INSTRUCTION_NODE = 7;
40455 var COMMENT_NODE                = NodeType.COMMENT_NODE                = 8;
40456 var DOCUMENT_NODE               = NodeType.DOCUMENT_NODE               = 9;
40457 var DOCUMENT_TYPE_NODE          = NodeType.DOCUMENT_TYPE_NODE          = 10;
40458 var DOCUMENT_FRAGMENT_NODE      = NodeType.DOCUMENT_FRAGMENT_NODE      = 11;
40459 var NOTATION_NODE               = NodeType.NOTATION_NODE               = 12;
40460
40461 // ExceptionCode
40462 var ExceptionCode = {};
40463 var ExceptionMessage = {};
40464 var INDEX_SIZE_ERR              = ExceptionCode.INDEX_SIZE_ERR              = ((ExceptionMessage[1]="Index size error"),1);
40465 var DOMSTRING_SIZE_ERR          = ExceptionCode.DOMSTRING_SIZE_ERR          = ((ExceptionMessage[2]="DOMString size error"),2);
40466 var HIERARCHY_REQUEST_ERR       = ExceptionCode.HIERARCHY_REQUEST_ERR       = ((ExceptionMessage[3]="Hierarchy request error"),3);
40467 var WRONG_DOCUMENT_ERR          = ExceptionCode.WRONG_DOCUMENT_ERR          = ((ExceptionMessage[4]="Wrong document"),4);
40468 var INVALID_CHARACTER_ERR       = ExceptionCode.INVALID_CHARACTER_ERR       = ((ExceptionMessage[5]="Invalid character"),5);
40469 var NO_DATA_ALLOWED_ERR         = ExceptionCode.NO_DATA_ALLOWED_ERR         = ((ExceptionMessage[6]="No data allowed"),6);
40470 var NO_MODIFICATION_ALLOWED_ERR = ExceptionCode.NO_MODIFICATION_ALLOWED_ERR = ((ExceptionMessage[7]="No modification allowed"),7);
40471 var NOT_FOUND_ERR               = ExceptionCode.NOT_FOUND_ERR               = ((ExceptionMessage[8]="Not found"),8);
40472 var NOT_SUPPORTED_ERR           = ExceptionCode.NOT_SUPPORTED_ERR           = ((ExceptionMessage[9]="Not supported"),9);
40473 var INUSE_ATTRIBUTE_ERR         = ExceptionCode.INUSE_ATTRIBUTE_ERR         = ((ExceptionMessage[10]="Attribute in use"),10);
40474 //level2
40475 var INVALID_STATE_ERR           = ExceptionCode.INVALID_STATE_ERR               = ((ExceptionMessage[11]="Invalid state"),11);
40476 var SYNTAX_ERR                  = ExceptionCode.SYNTAX_ERR                      = ((ExceptionMessage[12]="Syntax error"),12);
40477 var INVALID_MODIFICATION_ERR    = ExceptionCode.INVALID_MODIFICATION_ERR        = ((ExceptionMessage[13]="Invalid modification"),13);
40478 var NAMESPACE_ERR               = ExceptionCode.NAMESPACE_ERR                   = ((ExceptionMessage[14]="Invalid namespace"),14);
40479 var INVALID_ACCESS_ERR          = ExceptionCode.INVALID_ACCESS_ERR              = ((ExceptionMessage[15]="Invalid access"),15);
40480
40481
40482 function DOMException(code, message) {
40483         if(message instanceof Error){
40484                 var error = message;
40485         }else{
40486                 error = this;
40487                 Error.call(this, ExceptionMessage[code]);
40488                 this.message = ExceptionMessage[code];
40489                 if(Error.captureStackTrace) Error.captureStackTrace(this, DOMException);
40490         }
40491         error.code = code;
40492         if(message) this.message = this.message + ": " + message;
40493         return error;
40494 }
40495 DOMException.prototype = Error.prototype;
40496 copy(ExceptionCode,DOMException);
40497 /**
40498  * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-536297177
40499  * The NodeList interface provides the abstraction of an ordered collection of nodes, without defining or constraining how this collection is implemented. NodeList objects in the DOM are live.
40500  * The items in the NodeList are accessible via an integral index, starting from 0.
40501  */
40502 function NodeList() {
40503 }
40504 NodeList.prototype = {
40505         /**
40506          * The number of nodes in the list. The range of valid child node indices is 0 to length-1 inclusive.
40507          * @standard level1
40508          */
40509         length:0, 
40510         /**
40511          * Returns the indexth item in the collection. If index is greater than or equal to the number of nodes in the list, this returns null.
40512          * @standard level1
40513          * @param index  unsigned long 
40514          *   Index into the collection.
40515          * @return Node
40516          *      The node at the indexth position in the NodeList, or null if that is not a valid index. 
40517          */
40518         item: function(index) {
40519                 return this[index] || null;
40520         },
40521         toString:function(){
40522                 for(var buf = [], i = 0;i<this.length;i++){
40523                         serializeToString(this[i],buf);
40524                 }
40525                 return buf.join('');
40526         }
40527 };
40528 function LiveNodeList(node,refresh){
40529         this._node = node;
40530         this._refresh = refresh;
40531         _updateLiveList(this);
40532 }
40533 function _updateLiveList(list){
40534         var inc = list._node._inc || list._node.ownerDocument._inc;
40535         if(list._inc != inc){
40536                 var ls = list._refresh(list._node);
40537                 //console.log(ls.length)
40538                 __set__(list,'length',ls.length);
40539                 copy(ls,list);
40540                 list._inc = inc;
40541         }
40542 }
40543 LiveNodeList.prototype.item = function(i){
40544         _updateLiveList(this);
40545         return this[i];
40546 };
40547
40548 _extends(LiveNodeList,NodeList);
40549 /**
40550  * 
40551  * Objects implementing the NamedNodeMap interface are used to represent collections of nodes that can be accessed by name. Note that NamedNodeMap does not inherit from NodeList; NamedNodeMaps are not maintained in any particular order. Objects contained in an object implementing NamedNodeMap may also be accessed by an ordinal index, but this is simply to allow convenient enumeration of the contents of a NamedNodeMap, and does not imply that the DOM specifies an order to these Nodes.
40552  * NamedNodeMap objects in the DOM are live.
40553  * used for attributes or DocumentType entities 
40554  */
40555 function NamedNodeMap() {
40556 }
40557
40558 function _findNodeIndex(list,node){
40559         var i = list.length;
40560         while(i--){
40561                 if(list[i] === node){return i}
40562         }
40563 }
40564
40565 function _addNamedNode(el,list,newAttr,oldAttr){
40566         if(oldAttr){
40567                 list[_findNodeIndex(list,oldAttr)] = newAttr;
40568         }else{
40569                 list[list.length++] = newAttr;
40570         }
40571         if(el){
40572                 newAttr.ownerElement = el;
40573                 var doc = el.ownerDocument;
40574                 if(doc){
40575                         oldAttr && _onRemoveAttribute(doc,el,oldAttr);
40576                         _onAddAttribute(doc,el,newAttr);
40577                 }
40578         }
40579 }
40580 function _removeNamedNode(el,list,attr){
40581         var i = _findNodeIndex(list,attr);
40582         if(i>=0){
40583                 var lastIndex = list.length-1;
40584                 while(i<lastIndex){
40585                         list[i] = list[++i];
40586                 }
40587                 list.length = lastIndex;
40588                 if(el){
40589                         var doc = el.ownerDocument;
40590                         if(doc){
40591                                 _onRemoveAttribute(doc,el,attr);
40592                                 attr.ownerElement = null;
40593                         }
40594                 }
40595         }else{
40596                 throw DOMException(NOT_FOUND_ERR,new Error())
40597         }
40598 }
40599 NamedNodeMap.prototype = {
40600         length:0,
40601         item:NodeList.prototype.item,
40602         getNamedItem: function(key) {
40603 //              if(key.indexOf(':')>0 || key == 'xmlns'){
40604 //                      return null;
40605 //              }
40606                 var i = this.length;
40607                 while(i--){
40608                         var attr = this[i];
40609                         if(attr.nodeName == key){
40610                                 return attr;
40611                         }
40612                 }
40613         },
40614         setNamedItem: function(attr) {
40615                 var el = attr.ownerElement;
40616                 if(el && el!=this._ownerElement){
40617                         throw new DOMException(INUSE_ATTRIBUTE_ERR);
40618                 }
40619                 var oldAttr = this.getNamedItem(attr.nodeName);
40620                 _addNamedNode(this._ownerElement,this,attr,oldAttr);
40621                 return oldAttr;
40622         },
40623         /* returns Node */
40624         setNamedItemNS: function(attr) {// raises: WRONG_DOCUMENT_ERR,NO_MODIFICATION_ALLOWED_ERR,INUSE_ATTRIBUTE_ERR
40625                 var el = attr.ownerElement, oldAttr;
40626                 if(el && el!=this._ownerElement){
40627                         throw new DOMException(INUSE_ATTRIBUTE_ERR);
40628                 }
40629                 oldAttr = this.getNamedItemNS(attr.namespaceURI,attr.localName);
40630                 _addNamedNode(this._ownerElement,this,attr,oldAttr);
40631                 return oldAttr;
40632         },
40633
40634         /* returns Node */
40635         removeNamedItem: function(key) {
40636                 var attr = this.getNamedItem(key);
40637                 _removeNamedNode(this._ownerElement,this,attr);
40638                 return attr;
40639                 
40640                 
40641         },// raises: NOT_FOUND_ERR,NO_MODIFICATION_ALLOWED_ERR
40642         
40643         //for level2
40644         removeNamedItemNS:function(namespaceURI,localName){
40645                 var attr = this.getNamedItemNS(namespaceURI,localName);
40646                 _removeNamedNode(this._ownerElement,this,attr);
40647                 return attr;
40648         },
40649         getNamedItemNS: function(namespaceURI, localName) {
40650                 var i = this.length;
40651                 while(i--){
40652                         var node = this[i];
40653                         if(node.localName == localName && node.namespaceURI == namespaceURI){
40654                                 return node;
40655                         }
40656                 }
40657                 return null;
40658         }
40659 };
40660 /**
40661  * @see http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#ID-102161490
40662  */
40663 function DOMImplementation(/* Object */ features) {
40664         this._features = {};
40665         if (features) {
40666                 for (var feature in features) {
40667                          this._features = features[feature];
40668                 }
40669         }
40670 }
40671
40672 DOMImplementation.prototype = {
40673         hasFeature: function(/* string */ feature, /* string */ version) {
40674                 var versions = this._features[feature.toLowerCase()];
40675                 if (versions && (!version || version in versions)) {
40676                         return true;
40677                 } else {
40678                         return false;
40679                 }
40680         },
40681         // Introduced in DOM Level 2:
40682         createDocument:function(namespaceURI,  qualifiedName, doctype){// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR,WRONG_DOCUMENT_ERR
40683                 var doc = new Document();
40684                 doc.implementation = this;
40685                 doc.childNodes = new NodeList();
40686                 doc.doctype = doctype;
40687                 if(doctype){
40688                         doc.appendChild(doctype);
40689                 }
40690                 if(qualifiedName){
40691                         var root = doc.createElementNS(namespaceURI,qualifiedName);
40692                         doc.appendChild(root);
40693                 }
40694                 return doc;
40695         },
40696         // Introduced in DOM Level 2:
40697         createDocumentType:function(qualifiedName, publicId, systemId){// raises:INVALID_CHARACTER_ERR,NAMESPACE_ERR
40698                 var node = new DocumentType();
40699                 node.name = qualifiedName;
40700                 node.nodeName = qualifiedName;
40701                 node.publicId = publicId;
40702                 node.systemId = systemId;
40703                 // Introduced in DOM Level 2:
40704                 //readonly attribute DOMString        internalSubset;
40705                 
40706                 //TODO:..
40707                 //  readonly attribute NamedNodeMap     entities;
40708                 //  readonly attribute NamedNodeMap     notations;
40709                 return node;
40710         }
40711 };
40712
40713
40714 /**
40715  * @see http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113/core.html#ID-1950641247
40716  */
40717
40718 function Node() {
40719 }
40720
40721 Node.prototype = {
40722         firstChild : null,
40723         lastChild : null,
40724         previousSibling : null,
40725         nextSibling : null,
40726         attributes : null,
40727         parentNode : null,
40728         childNodes : null,
40729         ownerDocument : null,
40730         nodeValue : null,
40731         namespaceURI : null,
40732         prefix : null,
40733         localName : null,
40734         // Modified in DOM Level 2:
40735         insertBefore:function(newChild, refChild){//raises 
40736                 return _insertBefore(this,newChild,refChild);
40737         },
40738         replaceChild:function(newChild, oldChild){//raises 
40739                 this.insertBefore(newChild,oldChild);
40740                 if(oldChild){
40741                         this.removeChild(oldChild);
40742                 }
40743         },
40744         removeChild:function(oldChild){
40745                 return _removeChild(this,oldChild);
40746         },
40747         appendChild:function(newChild){
40748                 return this.insertBefore(newChild,null);
40749         },
40750         hasChildNodes:function(){
40751                 return this.firstChild != null;
40752         },
40753         cloneNode:function(deep){
40754                 return cloneNode(this.ownerDocument||this,this,deep);
40755         },
40756         // Modified in DOM Level 2:
40757         normalize:function(){
40758                 var child = this.firstChild;
40759                 while(child){
40760                         var next = child.nextSibling;
40761                         if(next && next.nodeType == TEXT_NODE && child.nodeType == TEXT_NODE){
40762                                 this.removeChild(next);
40763                                 child.appendData(next.data);
40764                         }else{
40765                                 child.normalize();
40766                                 child = next;
40767                         }
40768                 }
40769         },
40770         // Introduced in DOM Level 2:
40771         isSupported:function(feature, version){
40772                 return this.ownerDocument.implementation.hasFeature(feature,version);
40773         },
40774     // Introduced in DOM Level 2:
40775     hasAttributes:function(){
40776         return this.attributes.length>0;
40777     },
40778     lookupPrefix:function(namespaceURI){
40779         var el = this;
40780         while(el){
40781                 var map = el._nsMap;
40782                 //console.dir(map)
40783                 if(map){
40784                         for(var n in map){
40785                                 if(map[n] == namespaceURI){
40786                                         return n;
40787                                 }
40788                         }
40789                 }
40790                 el = el.nodeType == 2?el.ownerDocument : el.parentNode;
40791         }
40792         return null;
40793     },
40794     // Introduced in DOM Level 3:
40795     lookupNamespaceURI:function(prefix){
40796         var el = this;
40797         while(el){
40798                 var map = el._nsMap;
40799                 //console.dir(map)
40800                 if(map){
40801                         if(prefix in map){
40802                                 return map[prefix] ;
40803                         }
40804                 }
40805                 el = el.nodeType == 2?el.ownerDocument : el.parentNode;
40806         }
40807         return null;
40808     },
40809     // Introduced in DOM Level 3:
40810     isDefaultNamespace:function(namespaceURI){
40811         var prefix = this.lookupPrefix(namespaceURI);
40812         return prefix == null;
40813     }
40814 };
40815
40816
40817 function _xmlEncoder(c){
40818         return c == '<' && '&lt;' ||
40819          c == '>' && '&gt;' ||
40820          c == '&' && '&amp;' ||
40821          c == '"' && '&quot;' ||
40822          '&#'+c.charCodeAt()+';'
40823 }
40824
40825
40826 copy(NodeType,Node);
40827 copy(NodeType,Node.prototype);
40828
40829 /**
40830  * @param callback return true for continue,false for break
40831  * @return boolean true: break visit;
40832  */
40833 function _visitNode(node,callback){
40834         if(callback(node)){
40835                 return true;
40836         }
40837         if(node = node.firstChild){
40838                 do{
40839                         if(_visitNode(node,callback)){return true}
40840         }while(node=node.nextSibling)
40841     }
40842 }
40843
40844
40845
40846 function Document(){
40847 }
40848 function _onAddAttribute(doc,el,newAttr){
40849         doc && doc._inc++;
40850         var ns = newAttr.namespaceURI;
40851         if(ns == 'http://www.w3.org/2000/xmlns/'){
40852                 //update namespace
40853                 el._nsMap[newAttr.prefix?newAttr.localName:''] = newAttr.value;
40854         }
40855 }
40856 function _onRemoveAttribute(doc,el,newAttr,remove){
40857         doc && doc._inc++;
40858         var ns = newAttr.namespaceURI;
40859         if(ns == 'http://www.w3.org/2000/xmlns/'){
40860                 //update namespace
40861                 delete el._nsMap[newAttr.prefix?newAttr.localName:''];
40862         }
40863 }
40864 function _onUpdateChild(doc,el,newChild){
40865         if(doc && doc._inc){
40866                 doc._inc++;
40867                 //update childNodes
40868                 var cs = el.childNodes;
40869                 if(newChild){
40870                         cs[cs.length++] = newChild;
40871                 }else{
40872                         //console.log(1)
40873                         var child = el.firstChild;
40874                         var i = 0;
40875                         while(child){
40876                                 cs[i++] = child;
40877                                 child =child.nextSibling;
40878                         }
40879                         cs.length = i;
40880                 }
40881         }
40882 }
40883
40884 /**
40885  * attributes;
40886  * children;
40887  * 
40888  * writeable properties:
40889  * nodeValue,Attr:value,CharacterData:data
40890  * prefix
40891  */
40892 function _removeChild(parentNode,child){
40893         var previous = child.previousSibling;
40894         var next = child.nextSibling;
40895         if(previous){
40896                 previous.nextSibling = next;
40897         }else{
40898                 parentNode.firstChild = next;
40899         }
40900         if(next){
40901                 next.previousSibling = previous;
40902         }else{
40903                 parentNode.lastChild = previous;
40904         }
40905         _onUpdateChild(parentNode.ownerDocument,parentNode);
40906         return child;
40907 }
40908 /**
40909  * preformance key(refChild == null)
40910  */
40911 function _insertBefore(parentNode,newChild,nextChild){
40912         var cp = newChild.parentNode;
40913         if(cp){
40914                 cp.removeChild(newChild);//remove and update
40915         }
40916         if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
40917                 var newFirst = newChild.firstChild;
40918                 if (newFirst == null) {
40919                         return newChild;
40920                 }
40921                 var newLast = newChild.lastChild;
40922         }else{
40923                 newFirst = newLast = newChild;
40924         }
40925         var pre = nextChild ? nextChild.previousSibling : parentNode.lastChild;
40926
40927         newFirst.previousSibling = pre;
40928         newLast.nextSibling = nextChild;
40929         
40930         
40931         if(pre){
40932                 pre.nextSibling = newFirst;
40933         }else{
40934                 parentNode.firstChild = newFirst;
40935         }
40936         if(nextChild == null){
40937                 parentNode.lastChild = newLast;
40938         }else{
40939                 nextChild.previousSibling = newLast;
40940         }
40941         do{
40942                 newFirst.parentNode = parentNode;
40943         }while(newFirst !== newLast && (newFirst= newFirst.nextSibling))
40944         _onUpdateChild(parentNode.ownerDocument||parentNode,parentNode);
40945         //console.log(parentNode.lastChild.nextSibling == null)
40946         if (newChild.nodeType == DOCUMENT_FRAGMENT_NODE) {
40947                 newChild.firstChild = newChild.lastChild = null;
40948         }
40949         return newChild;
40950 }
40951 function _appendSingleChild(parentNode,newChild){
40952         var cp = newChild.parentNode;
40953         if(cp){
40954                 var pre = parentNode.lastChild;
40955                 cp.removeChild(newChild);//remove and update
40956                 var pre = parentNode.lastChild;
40957         }
40958         var pre = parentNode.lastChild;
40959         newChild.parentNode = parentNode;
40960         newChild.previousSibling = pre;
40961         newChild.nextSibling = null;
40962         if(pre){
40963                 pre.nextSibling = newChild;
40964         }else{
40965                 parentNode.firstChild = newChild;
40966         }
40967         parentNode.lastChild = newChild;
40968         _onUpdateChild(parentNode.ownerDocument,parentNode,newChild);
40969         return newChild;
40970         //console.log("__aa",parentNode.lastChild.nextSibling == null)
40971 }
40972 Document.prototype = {
40973         //implementation : null,
40974         nodeName :  '#document',
40975         nodeType :  DOCUMENT_NODE,
40976         doctype :  null,
40977         documentElement :  null,
40978         _inc : 1,
40979         
40980         insertBefore :  function(newChild, refChild){//raises 
40981                 if(newChild.nodeType == DOCUMENT_FRAGMENT_NODE){
40982                         var child = newChild.firstChild;
40983                         while(child){
40984                                 var next = child.nextSibling;
40985                                 this.insertBefore(child,refChild);
40986                                 child = next;
40987                         }
40988                         return newChild;
40989                 }
40990                 if(this.documentElement == null && newChild.nodeType == 1){
40991                         this.documentElement = newChild;
40992                 }
40993                 
40994                 return _insertBefore(this,newChild,refChild),(newChild.ownerDocument = this),newChild;
40995         },
40996         removeChild :  function(oldChild){
40997                 if(this.documentElement == oldChild){
40998                         this.documentElement = null;
40999                 }
41000                 return _removeChild(this,oldChild);
41001         },
41002         // Introduced in DOM Level 2:
41003         importNode : function(importedNode,deep){
41004                 return importNode(this,importedNode,deep);
41005         },
41006         // Introduced in DOM Level 2:
41007         getElementById :        function(id){
41008                 var rtv = null;
41009                 _visitNode(this.documentElement,function(node){
41010                         if(node.nodeType == 1){
41011                                 if(node.getAttribute('id') == id){
41012                                         rtv = node;
41013                                         return true;
41014                                 }
41015                         }
41016                 });
41017                 return rtv;
41018         },
41019         
41020         //document factory method:
41021         createElement : function(tagName){
41022                 var node = new Element();
41023                 node.ownerDocument = this;
41024                 node.nodeName = tagName;
41025                 node.tagName = tagName;
41026                 node.childNodes = new NodeList();
41027                 var attrs       = node.attributes = new NamedNodeMap();
41028                 attrs._ownerElement = node;
41029                 return node;
41030         },
41031         createDocumentFragment :        function(){
41032                 var node = new DocumentFragment();
41033                 node.ownerDocument = this;
41034                 node.childNodes = new NodeList();
41035                 return node;
41036         },
41037         createTextNode :        function(data){
41038                 var node = new Text();
41039                 node.ownerDocument = this;
41040                 node.appendData(data);
41041                 return node;
41042         },
41043         createComment : function(data){
41044                 var node = new Comment();
41045                 node.ownerDocument = this;
41046                 node.appendData(data);
41047                 return node;
41048         },
41049         createCDATASection :    function(data){
41050                 var node = new CDATASection();
41051                 node.ownerDocument = this;
41052                 node.appendData(data);
41053                 return node;
41054         },
41055         createProcessingInstruction :   function(target,data){
41056                 var node = new ProcessingInstruction();
41057                 node.ownerDocument = this;
41058                 node.tagName = node.target = target;
41059                 node.nodeValue= node.data = data;
41060                 return node;
41061         },
41062         createAttribute :       function(name){
41063                 var node = new Attr();
41064                 node.ownerDocument      = this;
41065                 node.name = name;
41066                 node.nodeName   = name;
41067                 node.localName = name;
41068                 node.specified = true;
41069                 return node;
41070         },
41071         createEntityReference : function(name){
41072                 var node = new EntityReference();
41073                 node.ownerDocument      = this;
41074                 node.nodeName   = name;
41075                 return node;
41076         },
41077         // Introduced in DOM Level 2:
41078         createElementNS :       function(namespaceURI,qualifiedName){
41079                 var node = new Element();
41080                 var pl = qualifiedName.split(':');
41081                 var attrs       = node.attributes = new NamedNodeMap();
41082                 node.childNodes = new NodeList();
41083                 node.ownerDocument = this;
41084                 node.nodeName = qualifiedName;
41085                 node.tagName = qualifiedName;
41086                 node.namespaceURI = namespaceURI;
41087                 if(pl.length == 2){
41088                         node.prefix = pl[0];
41089                         node.localName = pl[1];
41090                 }else{
41091                         //el.prefix = null;
41092                         node.localName = qualifiedName;
41093                 }
41094                 attrs._ownerElement = node;
41095                 return node;
41096         },
41097         // Introduced in DOM Level 2:
41098         createAttributeNS :     function(namespaceURI,qualifiedName){
41099                 var node = new Attr();
41100                 var pl = qualifiedName.split(':');
41101                 node.ownerDocument = this;
41102                 node.nodeName = qualifiedName;
41103                 node.name = qualifiedName;
41104                 node.namespaceURI = namespaceURI;
41105                 node.specified = true;
41106                 if(pl.length == 2){
41107                         node.prefix = pl[0];
41108                         node.localName = pl[1];
41109                 }else{
41110                         //el.prefix = null;
41111                         node.localName = qualifiedName;
41112                 }
41113                 return node;
41114         }
41115 };
41116 _extends(Document,Node);
41117
41118
41119 function Element() {
41120         this._nsMap = {};
41121 }
41122 Element.prototype = {
41123         nodeType : ELEMENT_NODE,
41124         hasAttribute : function(name){
41125                 return this.getAttributeNode(name)!=null;
41126         },
41127         getAttribute : function(name){
41128                 var attr = this.getAttributeNode(name);
41129                 return attr && attr.value || '';
41130         },
41131         getAttributeNode : function(name){
41132                 return this.attributes.getNamedItem(name);
41133         },
41134         setAttribute : function(name, value){
41135                 var attr = this.ownerDocument.createAttribute(name);
41136                 attr.value = attr.nodeValue = "" + value;
41137                 this.setAttributeNode(attr);
41138         },
41139         removeAttribute : function(name){
41140                 var attr = this.getAttributeNode(name);
41141                 attr && this.removeAttributeNode(attr);
41142         },
41143         
41144         //four real opeartion method
41145         appendChild:function(newChild){
41146                 if(newChild.nodeType === DOCUMENT_FRAGMENT_NODE){
41147                         return this.insertBefore(newChild,null);
41148                 }else{
41149                         return _appendSingleChild(this,newChild);
41150                 }
41151         },
41152         setAttributeNode : function(newAttr){
41153                 return this.attributes.setNamedItem(newAttr);
41154         },
41155         setAttributeNodeNS : function(newAttr){
41156                 return this.attributes.setNamedItemNS(newAttr);
41157         },
41158         removeAttributeNode : function(oldAttr){
41159                 return this.attributes.removeNamedItem(oldAttr.nodeName);
41160         },
41161         //get real attribute name,and remove it by removeAttributeNode
41162         removeAttributeNS : function(namespaceURI, localName){
41163                 var old = this.getAttributeNodeNS(namespaceURI, localName);
41164                 old && this.removeAttributeNode(old);
41165         },
41166         
41167         hasAttributeNS : function(namespaceURI, localName){
41168                 return this.getAttributeNodeNS(namespaceURI, localName)!=null;
41169         },
41170         getAttributeNS : function(namespaceURI, localName){
41171                 var attr = this.getAttributeNodeNS(namespaceURI, localName);
41172                 return attr && attr.value || '';
41173         },
41174         setAttributeNS : function(namespaceURI, qualifiedName, value){
41175                 var attr = this.ownerDocument.createAttributeNS(namespaceURI, qualifiedName);
41176                 attr.value = attr.nodeValue = "" + value;
41177                 this.setAttributeNode(attr);
41178         },
41179         getAttributeNodeNS : function(namespaceURI, localName){
41180                 return this.attributes.getNamedItemNS(namespaceURI, localName);
41181         },
41182         
41183         getElementsByTagName : function(tagName){
41184                 return new LiveNodeList(this,function(base){
41185                         var ls = [];
41186                         _visitNode(base,function(node){
41187                                 if(node !== base && node.nodeType == ELEMENT_NODE && (tagName === '*' || node.tagName == tagName)){
41188                                         ls.push(node);
41189                                 }
41190                         });
41191                         return ls;
41192                 });
41193         },
41194         getElementsByTagNameNS : function(namespaceURI, localName){
41195                 return new LiveNodeList(this,function(base){
41196                         var ls = [];
41197                         _visitNode(base,function(node){
41198                                 if(node !== base && node.nodeType === ELEMENT_NODE && (namespaceURI === '*' || node.namespaceURI === namespaceURI) && (localName === '*' || node.localName == localName)){
41199                                         ls.push(node);
41200                                 }
41201                         });
41202                         return ls;
41203                 });
41204         }
41205 };
41206 Document.prototype.getElementsByTagName = Element.prototype.getElementsByTagName;
41207 Document.prototype.getElementsByTagNameNS = Element.prototype.getElementsByTagNameNS;
41208
41209
41210 _extends(Element,Node);
41211 function Attr() {
41212 }
41213 Attr.prototype.nodeType = ATTRIBUTE_NODE;
41214 _extends(Attr,Node);
41215
41216
41217 function CharacterData() {
41218 }
41219 CharacterData.prototype = {
41220         data : '',
41221         substringData : function(offset, count) {
41222                 return this.data.substring(offset, offset+count);
41223         },
41224         appendData: function(text) {
41225                 text = this.data+text;
41226                 this.nodeValue = this.data = text;
41227                 this.length = text.length;
41228         },
41229         insertData: function(offset,text) {
41230                 this.replaceData(offset,0,text);
41231         
41232         },
41233         appendChild:function(newChild){
41234                 //if(!(newChild instanceof CharacterData)){
41235                         throw new Error(ExceptionMessage[3])
41236                 //}
41237                 return Node.prototype.appendChild.apply(this,arguments)
41238         },
41239         deleteData: function(offset, count) {
41240                 this.replaceData(offset,count,"");
41241         },
41242         replaceData: function(offset, count, text) {
41243                 var start = this.data.substring(0,offset);
41244                 var end = this.data.substring(offset+count);
41245                 text = start + text + end;
41246                 this.nodeValue = this.data = text;
41247                 this.length = text.length;
41248         }
41249 };
41250 _extends(CharacterData,Node);
41251 function Text() {
41252 }
41253 Text.prototype = {
41254         nodeName : "#text",
41255         nodeType : TEXT_NODE,
41256         splitText : function(offset) {
41257                 var text = this.data;
41258                 var newText = text.substring(offset);
41259                 text = text.substring(0, offset);
41260                 this.data = this.nodeValue = text;
41261                 this.length = text.length;
41262                 var newNode = this.ownerDocument.createTextNode(newText);
41263                 if(this.parentNode){
41264                         this.parentNode.insertBefore(newNode, this.nextSibling);
41265                 }
41266                 return newNode;
41267         }
41268 };
41269 _extends(Text,CharacterData);
41270 function Comment() {
41271 }
41272 Comment.prototype = {
41273         nodeName : "#comment",
41274         nodeType : COMMENT_NODE
41275 };
41276 _extends(Comment,CharacterData);
41277
41278 function CDATASection() {
41279 }
41280 CDATASection.prototype = {
41281         nodeName : "#cdata-section",
41282         nodeType : CDATA_SECTION_NODE
41283 };
41284 _extends(CDATASection,CharacterData);
41285
41286
41287 function DocumentType() {
41288 }
41289 DocumentType.prototype.nodeType = DOCUMENT_TYPE_NODE;
41290 _extends(DocumentType,Node);
41291
41292 function Notation() {
41293 }
41294 Notation.prototype.nodeType = NOTATION_NODE;
41295 _extends(Notation,Node);
41296
41297 function Entity() {
41298 }
41299 Entity.prototype.nodeType = ENTITY_NODE;
41300 _extends(Entity,Node);
41301
41302 function EntityReference() {
41303 }
41304 EntityReference.prototype.nodeType = ENTITY_REFERENCE_NODE;
41305 _extends(EntityReference,Node);
41306
41307 function DocumentFragment() {
41308 }
41309 DocumentFragment.prototype.nodeName =   "#document-fragment";
41310 DocumentFragment.prototype.nodeType =   DOCUMENT_FRAGMENT_NODE;
41311 _extends(DocumentFragment,Node);
41312
41313
41314 function ProcessingInstruction() {
41315 }
41316 ProcessingInstruction.prototype.nodeType = PROCESSING_INSTRUCTION_NODE;
41317 _extends(ProcessingInstruction,Node);
41318 function XMLSerializer(){}
41319 XMLSerializer.prototype.serializeToString = function(node,attributeSorter){
41320         return node.toString(attributeSorter);
41321 };
41322 Node.prototype.toString =function(attributeSorter){
41323         var buf = [];
41324         serializeToString(this,buf,attributeSorter);
41325         return buf.join('');
41326 };
41327 function serializeToString(node,buf,attributeSorter,isHTML){
41328         switch(node.nodeType){
41329         case ELEMENT_NODE:
41330                 var attrs = node.attributes;
41331                 var len = attrs.length;
41332                 var child = node.firstChild;
41333                 var nodeName = node.tagName;
41334                 isHTML =  (htmlns === node.namespaceURI) ||isHTML; 
41335                 buf.push('<',nodeName);
41336                 if(attributeSorter){
41337                         buf.sort.apply(attrs, attributeSorter);
41338                 }
41339                 for(var i=0;i<len;i++){
41340                         serializeToString(attrs.item(i),buf,attributeSorter,isHTML);
41341                 }
41342                 if(child || isHTML && !/^(?:meta|link|img|br|hr|input|button)$/i.test(nodeName)){
41343                         buf.push('>');
41344                         //if is cdata child node
41345                         if(isHTML && /^script$/i.test(nodeName)){
41346                                 if(child){
41347                                         buf.push(child.data);
41348                                 }
41349                         }else{
41350                                 while(child){
41351                                         serializeToString(child,buf,attributeSorter,isHTML);
41352                                         child = child.nextSibling;
41353                                 }
41354                         }
41355                         buf.push('</',nodeName,'>');
41356                 }else{
41357                         buf.push('/>');
41358                 }
41359                 return;
41360         case DOCUMENT_NODE:
41361         case DOCUMENT_FRAGMENT_NODE:
41362                 var child = node.firstChild;
41363                 while(child){
41364                         serializeToString(child,buf,attributeSorter,isHTML);
41365                         child = child.nextSibling;
41366                 }
41367                 return;
41368         case ATTRIBUTE_NODE:
41369                 return buf.push(' ',node.name,'="',node.value.replace(/[<&"]/g,_xmlEncoder),'"');
41370         case TEXT_NODE:
41371                 return buf.push(node.data.replace(/[<&]/g,_xmlEncoder));
41372         case CDATA_SECTION_NODE:
41373                 return buf.push( '<![CDATA[',node.data,']]>');
41374         case COMMENT_NODE:
41375                 return buf.push( "<!--",node.data,"-->");
41376         case DOCUMENT_TYPE_NODE:
41377                 var pubid = node.publicId;
41378                 var sysid = node.systemId;
41379                 buf.push('<!DOCTYPE ',node.name);
41380                 if(pubid){
41381                         buf.push(' PUBLIC "',pubid);
41382                         if (sysid && sysid!='.') {
41383                                 buf.push( '" "',sysid);
41384                         }
41385                         buf.push('">');
41386                 }else if(sysid && sysid!='.'){
41387                         buf.push(' SYSTEM "',sysid,'">');
41388                 }else{
41389                         var sub = node.internalSubset;
41390                         if(sub){
41391                                 buf.push(" [",sub,"]");
41392                         }
41393                         buf.push(">");
41394                 }
41395                 return;
41396         case PROCESSING_INSTRUCTION_NODE:
41397                 return buf.push( "<?",node.target," ",node.data,"?>");
41398         case ENTITY_REFERENCE_NODE:
41399                 return buf.push( '&',node.nodeName,';');
41400         //case ENTITY_NODE:
41401         //case NOTATION_NODE:
41402         default:
41403                 buf.push('??',node.nodeName);
41404         }
41405 }
41406 function importNode(doc,node,deep){
41407         var node2;
41408         switch (node.nodeType) {
41409         case ELEMENT_NODE:
41410                 node2 = node.cloneNode(false);
41411                 node2.ownerDocument = doc;
41412                 //var attrs = node2.attributes;
41413                 //var len = attrs.length;
41414                 //for(var i=0;i<len;i++){
41415                         //node2.setAttributeNodeNS(importNode(doc,attrs.item(i),deep));
41416                 //}
41417         case DOCUMENT_FRAGMENT_NODE:
41418                 break;
41419         case ATTRIBUTE_NODE:
41420                 deep = true;
41421                 break;
41422         //case ENTITY_REFERENCE_NODE:
41423         //case PROCESSING_INSTRUCTION_NODE:
41424         ////case TEXT_NODE:
41425         //case CDATA_SECTION_NODE:
41426         //case COMMENT_NODE:
41427         //      deep = false;
41428         //      break;
41429         //case DOCUMENT_NODE:
41430         //case DOCUMENT_TYPE_NODE:
41431         //cannot be imported.
41432         //case ENTITY_NODE:
41433         //case NOTATION_NODE:
41434         //can not hit in level3
41435         //default:throw e;
41436         }
41437         if(!node2){
41438                 node2 = node.cloneNode(false);//false
41439         }
41440         node2.ownerDocument = doc;
41441         node2.parentNode = null;
41442         if(deep){
41443                 var child = node.firstChild;
41444                 while(child){
41445                         node2.appendChild(importNode(doc,child,deep));
41446                         child = child.nextSibling;
41447                 }
41448         }
41449         return node2;
41450 }
41451 //
41452 //var _relationMap = {firstChild:1,lastChild:1,previousSibling:1,nextSibling:1,
41453 //                                      attributes:1,childNodes:1,parentNode:1,documentElement:1,doctype,};
41454 function cloneNode(doc,node,deep){
41455         var node2 = new node.constructor();
41456         for(var n in node){
41457                 var v = node[n];
41458                 if(typeof v != 'object' ){
41459                         if(v != node2[n]){
41460                                 node2[n] = v;
41461                         }
41462                 }
41463         }
41464         if(node.childNodes){
41465                 node2.childNodes = new NodeList();
41466         }
41467         node2.ownerDocument = doc;
41468         switch (node2.nodeType) {
41469         case ELEMENT_NODE:
41470                 var attrs       = node.attributes;
41471                 var attrs2      = node2.attributes = new NamedNodeMap();
41472                 var len = attrs.length;
41473                 attrs2._ownerElement = node2;
41474                 for(var i=0;i<len;i++){
41475                         node2.setAttributeNode(cloneNode(doc,attrs.item(i),true));
41476                 }
41477                 break;;
41478         case ATTRIBUTE_NODE:
41479                 deep = true;
41480         }
41481         if(deep){
41482                 var child = node.firstChild;
41483                 while(child){
41484                         node2.appendChild(cloneNode(doc,child,deep));
41485                         child = child.nextSibling;
41486                 }
41487         }
41488         return node2;
41489 }
41490
41491 function __set__(object,key,value){
41492         object[key] = value;
41493 }
41494 //do dynamic
41495 try{
41496         if(Object.defineProperty){
41497                 Object.defineProperty(LiveNodeList.prototype,'length',{
41498                         get:function(){
41499                                 _updateLiveList(this);
41500                                 return this.$$length;
41501                         }
41502                 });
41503                 Object.defineProperty(Node.prototype,'textContent',{
41504                         get:function(){
41505                                 return getTextContent(this);
41506                         },
41507                         set:function(data){
41508                                 switch(this.nodeType){
41509                                 case 1:
41510                                 case 11:
41511                                         while(this.firstChild){
41512                                                 this.removeChild(this.firstChild);
41513                                         }
41514                                         if(data || String(data)){
41515                                                 this.appendChild(this.ownerDocument.createTextNode(data));
41516                                         }
41517                                         break;
41518                                 default:
41519                                         //TODO:
41520                                         this.data = data;
41521                                         this.value = value;
41522                                         this.nodeValue = data;
41523                                 }
41524                         }
41525                 });
41526                 
41527                 function getTextContent(node){
41528                         switch(node.nodeType){
41529                         case 1:
41530                         case 11:
41531                                 var buf = [];
41532                                 node = node.firstChild;
41533                                 while(node){
41534                                         if(node.nodeType!==7 && node.nodeType !==8){
41535                                                 buf.push(getTextContent(node));
41536                                         }
41537                                         node = node.nextSibling;
41538                                 }
41539                                 return buf.join('');
41540                         default:
41541                                 return node.nodeValue;
41542                         }
41543                 }
41544                 __set__ = function(object,key,value){
41545                         //console.log(value)
41546                         object['$$'+key] = value;
41547                 };
41548         }
41549 }catch(e){//ie8
41550 }
41551
41552 if(typeof commonjsRequire == 'function'){
41553         exports.DOMImplementation = DOMImplementation;
41554         exports.XMLSerializer = XMLSerializer;
41555 }
41556 });
41557
41558 var domParser = createCommonjsModule(function (module, exports) {
41559 function DOMParser(options){
41560         this.options = options ||{locator:{}};
41561         
41562 }
41563 DOMParser.prototype.parseFromString = function(source,mimeType){        
41564         var options = this.options;
41565         var sax$$1 =  new XMLReader();
41566         var domBuilder = options.domBuilder || new DOMHandler();//contentHandler and LexicalHandler
41567         var errorHandler = options.errorHandler;
41568         var locator = options.locator;
41569         var defaultNSMap = options.xmlns||{};
41570         var entityMap = {'lt':'<','gt':'>','amp':'&','quot':'"','apos':"'"};
41571         if(locator){
41572                 domBuilder.setDocumentLocator(locator);
41573         }
41574         
41575         sax$$1.errorHandler = buildErrorHandler(errorHandler,domBuilder,locator);
41576         sax$$1.domBuilder = options.domBuilder || domBuilder;
41577         if(/\/x?html?$/.test(mimeType)){
41578                 entityMap.nbsp = '\xa0';
41579                 entityMap.copy = '\xa9';
41580                 defaultNSMap['']= 'http://www.w3.org/1999/xhtml';
41581         }
41582         defaultNSMap.xml = defaultNSMap.xml || 'http://www.w3.org/XML/1998/namespace';
41583         if(source){
41584                 sax$$1.parse(source,defaultNSMap,entityMap);
41585         }else{
41586                 sax$$1.errorHandler.error("invalid document source");
41587         }
41588         return domBuilder.document;
41589 };
41590 function buildErrorHandler(errorImpl,domBuilder,locator){
41591         if(!errorImpl){
41592                 if(domBuilder instanceof DOMHandler){
41593                         return domBuilder;
41594                 }
41595                 errorImpl = domBuilder ;
41596         }
41597         var errorHandler = {};
41598         var isCallback = errorImpl instanceof Function;
41599         locator = locator||{};
41600         function build(key){
41601                 var fn = errorImpl[key];
41602                 if(!fn && isCallback){
41603                         fn = errorImpl.length == 2?function(msg){errorImpl(key,msg);}:errorImpl;
41604                 }
41605                 errorHandler[key] = fn && function(msg){
41606                         fn('[xmldom '+key+']\t'+msg+_locator(locator));
41607                 }||function(){};
41608         }
41609         build('warning');
41610         build('error');
41611         build('fatalError');
41612         return errorHandler;
41613 }
41614
41615 //console.log('#\n\n\n\n\n\n\n####')
41616 /**
41617  * +ContentHandler+ErrorHandler
41618  * +LexicalHandler+EntityResolver2
41619  * -DeclHandler-DTDHandler 
41620  * 
41621  * DefaultHandler:EntityResolver, DTDHandler, ContentHandler, ErrorHandler
41622  * DefaultHandler2:DefaultHandler,LexicalHandler, DeclHandler, EntityResolver2
41623  * @link http://www.saxproject.org/apidoc/org/xml/sax/helpers/DefaultHandler.html
41624  */
41625 function DOMHandler() {
41626     this.cdata = false;
41627 }
41628 function position(locator,node){
41629         node.lineNumber = locator.lineNumber;
41630         node.columnNumber = locator.columnNumber;
41631 }
41632 /**
41633  * @see org.xml.sax.ContentHandler#startDocument
41634  * @link http://www.saxproject.org/apidoc/org/xml/sax/ContentHandler.html
41635  */ 
41636 DOMHandler.prototype = {
41637         startDocument : function() {
41638         this.document = new DOMImplementation().createDocument(null, null, null);
41639         if (this.locator) {
41640                 this.document.documentURI = this.locator.systemId;
41641         }
41642         },
41643         startElement:function(namespaceURI, localName, qName, attrs) {
41644                 var doc = this.document;
41645             var el = doc.createElementNS(namespaceURI, qName||localName);
41646             var len = attrs.length;
41647             appendElement(this, el);
41648             this.currentElement = el;
41649             
41650                 this.locator && position(this.locator,el);
41651             for (var i = 0 ; i < len; i++) {
41652                 var namespaceURI = attrs.getURI(i);
41653                 var value = attrs.getValue(i);
41654                 var qName = attrs.getQName(i);
41655                         var attr = doc.createAttributeNS(namespaceURI, qName);
41656                         if( attr.getOffset){
41657                                 position(attr.getOffset(1),attr);
41658                         }
41659                         attr.value = attr.nodeValue = value;
41660                         el.setAttributeNode(attr);
41661             }
41662         },
41663         endElement:function(namespaceURI, localName, qName) {
41664                 var current = this.currentElement;
41665             var tagName = current.tagName;
41666             this.currentElement = current.parentNode;
41667         },
41668         startPrefixMapping:function(prefix, uri) {
41669         },
41670         endPrefixMapping:function(prefix) {
41671         },
41672         processingInstruction:function(target, data) {
41673             var ins = this.document.createProcessingInstruction(target, data);
41674             this.locator && position(this.locator,ins);
41675             appendElement(this, ins);
41676         },
41677         ignorableWhitespace:function(ch, start, length) {
41678         },
41679         characters:function(chars, start, length) {
41680                 chars = _toString.apply(this,arguments);
41681                 //console.log(chars)
41682                 if(this.currentElement && chars){
41683                         if (this.cdata) {
41684                                 var charNode = this.document.createCDATASection(chars);
41685                                 this.currentElement.appendChild(charNode);
41686                         } else {
41687                                 var charNode = this.document.createTextNode(chars);
41688                                 this.currentElement.appendChild(charNode);
41689                         }
41690                         this.locator && position(this.locator,charNode);
41691                 }
41692         },
41693         skippedEntity:function(name) {
41694         },
41695         endDocument:function() {
41696                 this.document.normalize();
41697         },
41698         setDocumentLocator:function (locator) {
41699             if(this.locator = locator){// && !('lineNumber' in locator)){
41700                 locator.lineNumber = 0;
41701             }
41702         },
41703         //LexicalHandler
41704         comment:function(chars, start, length) {
41705                 chars = _toString.apply(this,arguments);
41706             var comm = this.document.createComment(chars);
41707             this.locator && position(this.locator,comm);
41708             appendElement(this, comm);
41709         },
41710         
41711         startCDATA:function() {
41712             //used in characters() methods
41713             this.cdata = true;
41714         },
41715         endCDATA:function() {
41716             this.cdata = false;
41717         },
41718         
41719         startDTD:function(name, publicId, systemId) {
41720                 var impl = this.document.implementation;
41721             if (impl && impl.createDocumentType) {
41722                 var dt = impl.createDocumentType(name, publicId, systemId);
41723                 this.locator && position(this.locator,dt);
41724                 appendElement(this, dt);
41725             }
41726         },
41727         /**
41728          * @see org.xml.sax.ErrorHandler
41729          * @link http://www.saxproject.org/apidoc/org/xml/sax/ErrorHandler.html
41730          */
41731         warning:function(error) {
41732                 console.warn('[xmldom warning]\t'+error,_locator(this.locator));
41733         },
41734         error:function(error) {
41735                 console.error('[xmldom error]\t'+error,_locator(this.locator));
41736         },
41737         fatalError:function(error) {
41738                 console.error('[xmldom fatalError]\t'+error,_locator(this.locator));
41739             throw error;
41740         }
41741 };
41742 function _locator(l){
41743         if(l){
41744                 return '\n@'+(l.systemId ||'')+'#[line:'+l.lineNumber+',col:'+l.columnNumber+']'
41745         }
41746 }
41747 function _toString(chars,start,length){
41748         if(typeof chars == 'string'){
41749                 return chars.substr(start,length)
41750         }else{//java sax connect width xmldom on rhino(what about: "? && !(chars instanceof String)")
41751                 if(chars.length >= start+length || start){
41752                         return new java.lang.String(chars,start,length)+'';
41753                 }
41754                 return chars;
41755         }
41756 }
41757
41758 /*
41759  * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/LexicalHandler.html
41760  * used method of org.xml.sax.ext.LexicalHandler:
41761  *  #comment(chars, start, length)
41762  *  #startCDATA()
41763  *  #endCDATA()
41764  *  #startDTD(name, publicId, systemId)
41765  *
41766  *
41767  * IGNORED method of org.xml.sax.ext.LexicalHandler:
41768  *  #endDTD()
41769  *  #startEntity(name)
41770  *  #endEntity(name)
41771  *
41772  *
41773  * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/DeclHandler.html
41774  * IGNORED method of org.xml.sax.ext.DeclHandler
41775  *      #attributeDecl(eName, aName, type, mode, value)
41776  *  #elementDecl(name, model)
41777  *  #externalEntityDecl(name, publicId, systemId)
41778  *  #internalEntityDecl(name, value)
41779  * @link http://www.saxproject.org/apidoc/org/xml/sax/ext/EntityResolver2.html
41780  * IGNORED method of org.xml.sax.EntityResolver2
41781  *  #resolveEntity(String name,String publicId,String baseURI,String systemId)
41782  *  #resolveEntity(publicId, systemId)
41783  *  #getExternalSubset(name, baseURI)
41784  * @link http://www.saxproject.org/apidoc/org/xml/sax/DTDHandler.html
41785  * IGNORED method of org.xml.sax.DTDHandler
41786  *  #notationDecl(name, publicId, systemId) {};
41787  *  #unparsedEntityDecl(name, publicId, systemId, notationName) {};
41788  */
41789 "endDTD,startEntity,endEntity,attributeDecl,elementDecl,externalEntityDecl,internalEntityDecl,resolveEntity,getExternalSubset,notationDecl,unparsedEntityDecl".replace(/\w+/g,function(key){
41790         DOMHandler.prototype[key] = function(){return null};
41791 });
41792
41793 /* Private static helpers treated below as private instance methods, so don't need to add these to the public API; we might use a Relator to also get rid of non-standard public properties */
41794 function appendElement (hander,node) {
41795     if (!hander.currentElement) {
41796         hander.document.appendChild(node);
41797     } else {
41798         hander.currentElement.appendChild(node);
41799     }
41800 }//appendChild and setAttributeNS are preformance key
41801
41802 if(typeof commonjsRequire == 'function'){
41803         var XMLReader = sax.XMLReader;
41804         var DOMImplementation = exports.DOMImplementation = dom.DOMImplementation;
41805         exports.XMLSerializer = dom.XMLSerializer ;
41806         exports.DOMParser = DOMParser;
41807 }
41808 });
41809
41810 var togeojson = createCommonjsModule(function (module, exports) {
41811 var toGeoJSON = (function() {
41812     'use strict';
41813
41814     var removeSpace = /\s*/g,
41815         trimSpace = /^\s*|\s*$/g,
41816         splitSpace = /\s+/;
41817     // generate a short, numeric hash of a string
41818     function okhash(x) {
41819         if (!x || !x.length) return 0;
41820         for (var i = 0, h = 0; i < x.length; i++) {
41821             h = ((h << 5) - h) + x.charCodeAt(i) | 0;
41822         } return h;
41823     }
41824     // all Y children of X
41825     function get(x, y) { return x.getElementsByTagName(y); }
41826     function attr(x, y) { return x.getAttribute(y); }
41827     function attrf(x, y) { return parseFloat(attr(x, y)); }
41828     // one Y child of X, if any, otherwise null
41829     function get1(x, y) { var n = get(x, y); return n.length ? n[0] : null; }
41830     // https://developer.mozilla.org/en-US/docs/Web/API/Node.normalize
41831     function norm(el) { if (el.normalize) { el.normalize(); } return el; }
41832     // cast array x into numbers
41833     function numarray(x) {
41834         for (var j = 0, o = []; j < x.length; j++) { o[j] = parseFloat(x[j]); }
41835         return o;
41836     }
41837     // get the content of a text node, if any
41838     function nodeVal(x) {
41839         if (x) { norm(x); }
41840         return (x && x.textContent) || '';
41841     }
41842     // get the contents of multiple text nodes, if present
41843     function getMulti(x, ys) {
41844         var o = {}, n, k;
41845         for (k = 0; k < ys.length; k++) {
41846             n = get1(x, ys[k]);
41847             if (n) o[ys[k]] = nodeVal(n);
41848         }
41849         return o;
41850     }
41851     // add properties of Y to X, overwriting if present in both
41852     function extend(x, y) { for (var k in y) x[k] = y[k]; }
41853     // get one coordinate from a coordinate array, if any
41854     function coord1(v) { return numarray(v.replace(removeSpace, '').split(',')); }
41855     // get all coordinates from a coordinate array as [[],[]]
41856     function coord(v) {
41857         var coords = v.replace(trimSpace, '').split(splitSpace),
41858             o = [];
41859         for (var i = 0; i < coords.length; i++) {
41860             o.push(coord1(coords[i]));
41861         }
41862         return o;
41863     }
41864     function coordPair(x) {
41865         var ll = [attrf(x, 'lon'), attrf(x, 'lat')],
41866             ele = get1(x, 'ele'),
41867             // handle namespaced attribute in browser
41868             heartRate = get1(x, 'gpxtpx:hr') || get1(x, 'hr'),
41869             time = get1(x, 'time'),
41870             e;
41871         if (ele) {
41872             e = parseFloat(nodeVal(ele));
41873             if (!isNaN(e)) {
41874                 ll.push(e);
41875             }
41876         }
41877         return {
41878             coordinates: ll,
41879             time: time ? nodeVal(time) : null,
41880             heartRate: heartRate ? parseFloat(nodeVal(heartRate)) : null
41881         };
41882     }
41883
41884     // create a new feature collection parent object
41885     function fc() {
41886         return {
41887             type: 'FeatureCollection',
41888             features: []
41889         };
41890     }
41891
41892     var serializer;
41893     if (typeof XMLSerializer !== 'undefined') {
41894         /* istanbul ignore next */
41895         serializer = new XMLSerializer();
41896     // only require xmldom in a node environment
41897     } else if (typeof exports === 'object' && typeof process === 'object' && !process.browser) {
41898         serializer = new (domParser.XMLSerializer)();
41899     }
41900     function xml2str(str) {
41901         // IE9 will create a new XMLSerializer but it'll crash immediately.
41902         // This line is ignored because we don't run coverage tests in IE9
41903         /* istanbul ignore next */
41904         if (str.xml !== undefined) return str.xml;
41905         return serializer.serializeToString(str);
41906     }
41907
41908     var t = {
41909         kml: function(doc) {
41910
41911             var gj = fc(),
41912                 // styleindex keeps track of hashed styles in order to match features
41913                 styleIndex = {}, styleByHash = {},
41914                 // stylemapindex keeps track of style maps to expose in properties
41915                 styleMapIndex = {},
41916                 // atomic geospatial types supported by KML - MultiGeometry is
41917                 // handled separately
41918                 geotypes = ['Polygon', 'LineString', 'Point', 'Track', 'gx:Track'],
41919                 // all root placemarks in the file
41920                 placemarks = get(doc, 'Placemark'),
41921                 styles = get(doc, 'Style'),
41922                 styleMaps = get(doc, 'StyleMap');
41923
41924             for (var k = 0; k < styles.length; k++) {
41925                 var hash = okhash(xml2str(styles[k])).toString(16);
41926                 styleIndex['#' + attr(styles[k], 'id')] = hash;
41927                 styleByHash[hash] = styles[k];
41928             }
41929             for (var l = 0; l < styleMaps.length; l++) {
41930                 styleIndex['#' + attr(styleMaps[l], 'id')] = okhash(xml2str(styleMaps[l])).toString(16);
41931                 var pairs = get(styleMaps[l], 'Pair');
41932                 var pairsMap = {};
41933                 for (var m = 0; m < pairs.length; m++) {
41934                     pairsMap[nodeVal(get1(pairs[m], 'key'))] = nodeVal(get1(pairs[m], 'styleUrl'));
41935                 }
41936                 styleMapIndex['#' + attr(styleMaps[l], 'id')] = pairsMap;
41937
41938             }
41939             for (var j = 0; j < placemarks.length; j++) {
41940                 gj.features = gj.features.concat(getPlacemark(placemarks[j]));
41941             }
41942             function kmlColor(v) {
41943                 var color, opacity;
41944                 v = v || '';
41945                 if (v.substr(0, 1) === '#') { v = v.substr(1); }
41946                 if (v.length === 6 || v.length === 3) { color = v; }
41947                 if (v.length === 8) {
41948                     opacity = parseInt(v.substr(0, 2), 16) / 255;
41949                     color = '#' + v.substr(6, 2) +
41950                         v.substr(4, 2) +
41951                         v.substr(2, 2);
41952                 }
41953                 return [color, isNaN(opacity) ? undefined : opacity];
41954             }
41955             function gxCoord(v) { return numarray(v.split(' ')); }
41956             function gxCoords(root) {
41957                 var elems = get(root, 'coord', 'gx'), coords = [], times = [];
41958                 if (elems.length === 0) elems = get(root, 'gx:coord');
41959                 for (var i = 0; i < elems.length; i++) coords.push(gxCoord(nodeVal(elems[i])));
41960                 var timeElems = get(root, 'when');
41961                 for (var j = 0; j < timeElems.length; j++) times.push(nodeVal(timeElems[j]));
41962                 return {
41963                     coords: coords,
41964                     times: times
41965                 };
41966             }
41967             function getGeometry(root) {
41968                 var geomNode, geomNodes, i, j, k, geoms = [], coordTimes = [];
41969                 if (get1(root, 'MultiGeometry')) { return getGeometry(get1(root, 'MultiGeometry')); }
41970                 if (get1(root, 'MultiTrack')) { return getGeometry(get1(root, 'MultiTrack')); }
41971                 if (get1(root, 'gx:MultiTrack')) { return getGeometry(get1(root, 'gx:MultiTrack')); }
41972                 for (i = 0; i < geotypes.length; i++) {
41973                     geomNodes = get(root, geotypes[i]);
41974                     if (geomNodes) {
41975                         for (j = 0; j < geomNodes.length; j++) {
41976                             geomNode = geomNodes[j];
41977                             if (geotypes[i] === 'Point') {
41978                                 geoms.push({
41979                                     type: 'Point',
41980                                     coordinates: coord1(nodeVal(get1(geomNode, 'coordinates')))
41981                                 });
41982                             } else if (geotypes[i] === 'LineString') {
41983                                 geoms.push({
41984                                     type: 'LineString',
41985                                     coordinates: coord(nodeVal(get1(geomNode, 'coordinates')))
41986                                 });
41987                             } else if (geotypes[i] === 'Polygon') {
41988                                 var rings = get(geomNode, 'LinearRing'),
41989                                     coords = [];
41990                                 for (k = 0; k < rings.length; k++) {
41991                                     coords.push(coord(nodeVal(get1(rings[k], 'coordinates'))));
41992                                 }
41993                                 geoms.push({
41994                                     type: 'Polygon',
41995                                     coordinates: coords
41996                                 });
41997                             } else if (geotypes[i] === 'Track' ||
41998                                 geotypes[i] === 'gx:Track') {
41999                                 var track = gxCoords(geomNode);
42000                                 geoms.push({
42001                                     type: 'LineString',
42002                                     coordinates: track.coords
42003                                 });
42004                                 if (track.times.length) coordTimes.push(track.times);
42005                             }
42006                         }
42007                     }
42008                 }
42009                 return {
42010                     geoms: geoms,
42011                     coordTimes: coordTimes
42012                 };
42013             }
42014             function getPlacemark(root) {
42015                 var geomsAndTimes = getGeometry(root), i, properties = {},
42016                     name = nodeVal(get1(root, 'name')),
42017                     styleUrl = nodeVal(get1(root, 'styleUrl')),
42018                     description = nodeVal(get1(root, 'description')),
42019                     timeSpan = get1(root, 'TimeSpan'),
42020                     timeStamp = get1(root, 'TimeStamp'),
42021                     extendedData = get1(root, 'ExtendedData'),
42022                     lineStyle = get1(root, 'LineStyle'),
42023                     polyStyle = get1(root, 'PolyStyle'),
42024                     visibility = get1(root, 'visibility');
42025
42026                 if (!geomsAndTimes.geoms.length) return [];
42027                 if (name) properties.name = name;
42028                 if (styleUrl) {
42029                     if (styleUrl[0] !== '#') {
42030                         styleUrl = '#' + styleUrl;
42031                     }
42032
42033                     properties.styleUrl = styleUrl;
42034                     if (styleIndex[styleUrl]) {
42035                         properties.styleHash = styleIndex[styleUrl];
42036                     }
42037                     if (styleMapIndex[styleUrl]) {
42038                         properties.styleMapHash = styleMapIndex[styleUrl];
42039                         properties.styleHash = styleIndex[styleMapIndex[styleUrl].normal];
42040                     }
42041                     // Try to populate the lineStyle or polyStyle since we got the style hash
42042                     var style = styleByHash[properties.styleHash];
42043                     if (style) {
42044                         if (!lineStyle) lineStyle = get1(style, 'LineStyle');
42045                         if (!polyStyle) polyStyle = get1(style, 'PolyStyle');
42046                     }
42047                 }
42048                 if (description) properties.description = description;
42049                 if (timeSpan) {
42050                     var begin = nodeVal(get1(timeSpan, 'begin'));
42051                     var end = nodeVal(get1(timeSpan, 'end'));
42052                     properties.timespan = { begin: begin, end: end };
42053                 }
42054                 if (timeStamp) {
42055                     properties.timestamp = nodeVal(get1(timeStamp, 'when'));
42056                 }
42057                 if (lineStyle) {
42058                     var linestyles = kmlColor(nodeVal(get1(lineStyle, 'color'))),
42059                         color = linestyles[0],
42060                         opacity = linestyles[1],
42061                         width = parseFloat(nodeVal(get1(lineStyle, 'width')));
42062                     if (color) properties.stroke = color;
42063                     if (!isNaN(opacity)) properties['stroke-opacity'] = opacity;
42064                     if (!isNaN(width)) properties['stroke-width'] = width;
42065                 }
42066                 if (polyStyle) {
42067                     var polystyles = kmlColor(nodeVal(get1(polyStyle, 'color'))),
42068                         pcolor = polystyles[0],
42069                         popacity = polystyles[1],
42070                         fill = nodeVal(get1(polyStyle, 'fill')),
42071                         outline = nodeVal(get1(polyStyle, 'outline'));
42072                     if (pcolor) properties.fill = pcolor;
42073                     if (!isNaN(popacity)) properties['fill-opacity'] = popacity;
42074                     if (fill) properties['fill-opacity'] = fill === '1' ? properties['fill-opacity'] || 1 : 0;
42075                     if (outline) properties['stroke-opacity'] = outline === '1' ? properties['stroke-opacity'] || 1 : 0;
42076                 }
42077                 if (extendedData) {
42078                     var datas = get(extendedData, 'Data'),
42079                         simpleDatas = get(extendedData, 'SimpleData');
42080
42081                     for (i = 0; i < datas.length; i++) {
42082                         properties[datas[i].getAttribute('name')] = nodeVal(get1(datas[i], 'value'));
42083                     }
42084                     for (i = 0; i < simpleDatas.length; i++) {
42085                         properties[simpleDatas[i].getAttribute('name')] = nodeVal(simpleDatas[i]);
42086                     }
42087                 }
42088                 if (visibility) {
42089                     properties.visibility = nodeVal(visibility);
42090                 }
42091                 if (geomsAndTimes.coordTimes.length) {
42092                     properties.coordTimes = (geomsAndTimes.coordTimes.length === 1) ?
42093                         geomsAndTimes.coordTimes[0] : geomsAndTimes.coordTimes;
42094                 }
42095                 var feature = {
42096                     type: 'Feature',
42097                     geometry: (geomsAndTimes.geoms.length === 1) ? geomsAndTimes.geoms[0] : {
42098                         type: 'GeometryCollection',
42099                         geometries: geomsAndTimes.geoms
42100                     },
42101                     properties: properties
42102                 };
42103                 if (attr(root, 'id')) feature.id = attr(root, 'id');
42104                 return [feature];
42105             }
42106             return gj;
42107         },
42108         gpx: function(doc) {
42109             var i,
42110                 tracks = get(doc, 'trk'),
42111                 routes = get(doc, 'rte'),
42112                 waypoints = get(doc, 'wpt'),
42113                 // a feature collection
42114                 gj = fc(),
42115                 feature;
42116             for (i = 0; i < tracks.length; i++) {
42117                 feature = getTrack(tracks[i]);
42118                 if (feature) gj.features.push(feature);
42119             }
42120             for (i = 0; i < routes.length; i++) {
42121                 feature = getRoute(routes[i]);
42122                 if (feature) gj.features.push(feature);
42123             }
42124             for (i = 0; i < waypoints.length; i++) {
42125                 gj.features.push(getPoint(waypoints[i]));
42126             }
42127             function getPoints(node, pointname) {
42128                 var pts = get(node, pointname),
42129                     line = [],
42130                     times = [],
42131                     heartRates = [],
42132                     l = pts.length;
42133                 if (l < 2) return {};  // Invalid line in GeoJSON
42134                 for (var i = 0; i < l; i++) {
42135                     var c = coordPair(pts[i]);
42136                     line.push(c.coordinates);
42137                     if (c.time) times.push(c.time);
42138                     if (c.heartRate) heartRates.push(c.heartRate);
42139                 }
42140                 return {
42141                     line: line,
42142                     times: times,
42143                     heartRates: heartRates
42144                 };
42145             }
42146             function getTrack(node) {
42147                 var segments = get(node, 'trkseg'),
42148                     track = [],
42149                     times = [],
42150                     heartRates = [],
42151                     line;
42152                 for (var i = 0; i < segments.length; i++) {
42153                     line = getPoints(segments[i], 'trkpt');
42154                     if (line) {
42155                         if (line.line) track.push(line.line);
42156                         if (line.times && line.times.length) times.push(line.times);
42157                         if (line.heartRates && line.heartRates.length) heartRates.push(line.heartRates);
42158                     }
42159                 }
42160                 if (track.length === 0) return;
42161                 var properties = getProperties(node);
42162                 if (times.length) properties.coordTimes = track.length === 1 ? times[0] : times;
42163                 if (heartRates.length) properties.heartRates = track.length === 1 ? heartRates[0] : heartRates;
42164                 return {
42165                     type: 'Feature',
42166                     properties: properties,
42167                     geometry: {
42168                         type: track.length === 1 ? 'LineString' : 'MultiLineString',
42169                         coordinates: track.length === 1 ? track[0] : track
42170                     }
42171                 };
42172             }
42173             function getRoute(node) {
42174                 var line = getPoints(node, 'rtept');
42175                 if (!line.line) return;
42176                 var routeObj = {
42177                     type: 'Feature',
42178                     properties: getProperties(node),
42179                     geometry: {
42180                         type: 'LineString',
42181                         coordinates: line.line
42182                     }
42183                 };
42184                 return routeObj;
42185             }
42186             function getPoint(node) {
42187                 var prop = getProperties(node);
42188                 extend(prop, getMulti(node, ['sym', 'type']));
42189                 return {
42190                     type: 'Feature',
42191                     properties: prop,
42192                     geometry: {
42193                         type: 'Point',
42194                         coordinates: coordPair(node).coordinates
42195                     }
42196                 };
42197             }
42198             function getProperties(node) {
42199                 var prop, links;
42200                 prop = getMulti(node, ['name', 'cmt', 'desc', 'time', 'keywords']);
42201                 links = get(node, 'link');
42202                 if (links.length) prop.links = [];
42203                 for (var i = 0, link; i < links.length; i++) {
42204                     link = { href: attr(links[i], 'href') };
42205                     extend(link, getMulti(links[i], ['text', 'type']));
42206                     prop.links.push(link);
42207                 }
42208                 return prop;
42209             }
42210             return gj;
42211         }
42212     };
42213     return t;
42214 })();
42215
42216 if (typeof module !== 'undefined') module.exports = toGeoJSON;
42217 });
42218
42219 function svgGpx(projection, context, dispatch$$1) {
42220     var showLabels = true,
42221         detected = utilDetect(),
42222         layer;
42223
42224
42225     function init() {
42226         if (svgGpx.initialized) return;  // run once
42227
42228         svgGpx.geojson = {};
42229         svgGpx.enabled = true;
42230
42231         function over() {
42232             event.stopPropagation();
42233             event.preventDefault();
42234             event.dataTransfer.dropEffect = 'copy';
42235         }
42236
42237         select('body')
42238             .attr('dropzone', 'copy')
42239             .on('drop.localgpx', function() {
42240                 event.stopPropagation();
42241                 event.preventDefault();
42242                 if (!detected.filedrop) return;
42243                 drawGpx.files(event.dataTransfer.files);
42244             })
42245             .on('dragenter.localgpx', over)
42246             .on('dragexit.localgpx', over)
42247             .on('dragover.localgpx', over);
42248
42249         svgGpx.initialized = true;
42250     }
42251
42252
42253     function drawGpx(selection$$1) {
42254         var geojson = svgGpx.geojson,
42255             enabled = svgGpx.enabled;
42256
42257         layer = selection$$1.selectAll('.layer-gpx')
42258             .data(enabled ? [0] : []);
42259
42260         layer.exit()
42261             .remove();
42262
42263         layer = layer.enter()
42264             .append('g')
42265             .attr('class', 'layer-gpx')
42266             .merge(layer);
42267
42268
42269         var paths = layer
42270             .selectAll('path')
42271             .data([geojson]);
42272
42273         paths.exit()
42274             .remove();
42275
42276         paths = paths.enter()
42277             .append('path')
42278             .attr('class', 'gpx')
42279             .merge(paths);
42280
42281
42282         var path$$1 = index$5(projection);
42283
42284         paths
42285             .attr('d', path$$1);
42286
42287
42288         var labels = layer.selectAll('text')
42289             .data(showLabels && geojson.features ? geojson.features : []);
42290
42291         labels.exit()
42292             .remove();
42293
42294         labels = labels.enter()
42295             .append('text')
42296             .attr('class', 'gpx')
42297             .merge(labels);
42298
42299         labels
42300             .text(function(d) {
42301                 return d.properties.desc || d.properties.name;
42302             })
42303             .attr('x', function(d) {
42304                 var centroid = path$$1.centroid(d);
42305                 return centroid[0] + 7;
42306             })
42307             .attr('y', function(d) {
42308                 var centroid = path$$1.centroid(d);
42309                 return centroid[1];
42310             });
42311
42312     }
42313
42314
42315     function toDom(x) {
42316         return (new DOMParser()).parseFromString(x, 'text/xml');
42317     }
42318
42319
42320     drawGpx.showLabels = function(_) {
42321         if (!arguments.length) return showLabels;
42322         showLabels = _;
42323         return this;
42324     };
42325
42326
42327     drawGpx.enabled = function(_) {
42328         if (!arguments.length) return svgGpx.enabled;
42329         svgGpx.enabled = _;
42330         dispatch$$1.call('change');
42331         return this;
42332     };
42333
42334
42335     drawGpx.hasGpx = function() {
42336         var geojson = svgGpx.geojson;
42337         return (!(lodash.isEmpty(geojson) || lodash.isEmpty(geojson.features)));
42338     };
42339
42340
42341     drawGpx.geojson = function(gj) {
42342         if (!arguments.length) return svgGpx.geojson;
42343         if (lodash.isEmpty(gj) || lodash.isEmpty(gj.features)) return this;
42344         svgGpx.geojson = gj;
42345         dispatch$$1.call('change');
42346         return this;
42347     };
42348
42349
42350     drawGpx.url = function(url) {
42351         text(url, function(err, data) {
42352             if (!err) {
42353                 drawGpx.geojson(togeojson.gpx(toDom(data)));
42354             }
42355         });
42356         return this;
42357     };
42358
42359
42360     drawGpx.files = function(fileList) {
42361         if (!fileList.length) return this;
42362         var f = fileList[0],
42363             reader = new FileReader();
42364
42365         reader.onload = function(e) {
42366             drawGpx.geojson(togeojson.gpx(toDom(e.target.result))).fitZoom();
42367         };
42368
42369         reader.readAsText(f);
42370         return this;
42371     };
42372
42373
42374     drawGpx.fitZoom = function() {
42375         if (!this.hasGpx()) return this;
42376         var geojson = svgGpx.geojson;
42377
42378         var map$$1 = context.map(),
42379             viewport = map$$1.trimmedExtent().polygon(),
42380             coords = lodash.reduce(geojson.features, function(coords, feature) {
42381                 var c = feature.geometry.coordinates;
42382                 return lodash.union(coords, feature.geometry.type === 'Point' ? [c] : c);
42383             }, []);
42384
42385         if (!geoPolygonIntersectsPolygon(viewport, coords, true)) {
42386             var extent$$1 = geoExtent$$1(bounds(geojson));
42387             map$$1.centerZoom(extent$$1.center(), map$$1.trimmedExtentZoom(extent$$1));
42388         }
42389
42390         return this;
42391     };
42392
42393
42394     init();
42395     return drawGpx;
42396 }
42397
42398 function svgIcon(name, svgklass, useklass) {
42399     return function drawIcon(selection) {
42400         selection.selectAll('svg')
42401             .data([0])
42402             .enter()
42403             .append('svg')
42404             .attr('class', 'icon ' + (svgklass || ''))
42405             .append('use')
42406             .attr('xlink:href', name)
42407             .attr('class', useklass);
42408     };
42409 }
42410
42411 function svgLabels(projection, context) {
42412     var path$$1 = index$5(projection),
42413         detected = utilDetect(),
42414         baselineHack = (detected.ie || detected.browser.toLowerCase() === 'edge'),
42415         rdrawn = index$8(),
42416         rskipped = index$8(),
42417         textWidthCache = {},
42418         entitybboxes = {};
42419
42420     // Listed from highest to lowest priority
42421     var labelStack = [
42422         ['line', 'aeroway', '*', 12],
42423         ['line', 'highway', 'motorway', 12],
42424         ['line', 'highway', 'trunk', 12],
42425         ['line', 'highway', 'primary', 12],
42426         ['line', 'highway', 'secondary', 12],
42427         ['line', 'highway', 'tertiary', 12],
42428         ['line', 'highway', '*', 12],
42429         ['line', 'railway', '*', 12],
42430         ['line', 'waterway', '*', 12],
42431         ['area', 'aeroway', '*', 12],
42432         ['area', 'amenity', '*', 12],
42433         ['area', 'building', '*', 12],
42434         ['area', 'historic', '*', 12],
42435         ['area', 'leisure', '*', 12],
42436         ['area', 'man_made', '*', 12],
42437         ['area', 'natural', '*', 12],
42438         ['area', 'shop', '*', 12],
42439         ['area', 'tourism', '*', 12],
42440         ['area', 'camp_site', '*', 12],
42441         ['point', 'aeroway', '*', 10],
42442         ['point', 'amenity', '*', 10],
42443         ['point', 'building', '*', 10],
42444         ['point', 'historic', '*', 10],
42445         ['point', 'leisure', '*', 10],
42446         ['point', 'man_made', '*', 10],
42447         ['point', 'natural', '*', 10],
42448         ['point', 'shop', '*', 10],
42449         ['point', 'tourism', '*', 10],
42450         ['point', 'camp_site', '*', 10],
42451         ['line', 'name', '*', 12],
42452         ['area', 'name', '*', 12],
42453         ['point', 'name', '*', 10]
42454     ];
42455
42456
42457     function blacklisted(preset) {
42458         var noIcons = ['building', 'landuse', 'natural'];
42459         return lodash.some(noIcons, function(s) {
42460             return preset.id.indexOf(s) >= 0;
42461         });
42462     }
42463
42464
42465     function get(array, prop) {
42466         return function(d, i) { return array[i][prop]; };
42467     }
42468
42469
42470     function textWidth(text$$1, size, elem) {
42471         var c = textWidthCache[size];
42472         if (!c) c = textWidthCache[size] = {};
42473
42474         if (c[text$$1]) {
42475             return c[text$$1];
42476
42477         } else if (elem) {
42478             c[text$$1] = elem.getComputedTextLength();
42479             return c[text$$1];
42480
42481         } else {
42482             var str = encodeURIComponent(text$$1).match(/%[CDEFcdef]/g);
42483             if (str === null) {
42484                 return size / 3 * 2 * text$$1.length;
42485             } else {
42486                 return size / 3 * (2 * text$$1.length + str.length);
42487             }
42488         }
42489     }
42490
42491
42492     function drawLinePaths(selection$$1, entities, filter, classes, labels) {
42493         var paths = selection$$1.selectAll('path')
42494             .filter(filter)
42495             .data(entities, osmEntity$$1.key);
42496
42497         paths.exit()
42498             .remove();
42499
42500         paths.enter()
42501             .append('path')
42502             .style('stroke-width', get(labels, 'font-size'))
42503             .attr('id', function(d) { return 'labelpath-' + d.id; })
42504             .attr('class', classes)
42505             .merge(paths)
42506             .attr('d', get(labels, 'lineString'));
42507     }
42508
42509
42510     function drawLineLabels(selection$$1, entities, filter, classes, labels) {
42511         var texts = selection$$1.selectAll('text.' + classes)
42512             .filter(filter)
42513             .data(entities, osmEntity$$1.key);
42514
42515         texts.exit()
42516             .remove();
42517
42518         texts.enter()
42519             .append('text')
42520             .attr('class', function(d, i) { return classes + ' ' + labels[i].classes + ' ' + d.id; })
42521             .attr('dy', baselineHack ? '0.35em' : null)
42522             .append('textPath')
42523             .attr('class', 'textpath');
42524
42525         texts = selection$$1.selectAll('text.' + classes);
42526
42527         texts.selectAll('.textpath')
42528             .filter(filter)
42529             .data(entities, osmEntity$$1.key)
42530             .attr('startOffset', '50%')
42531             .attr('xlink:href', function(d) { return '#labelpath-' + d.id; })
42532             .text(utilDisplayName);
42533     }
42534
42535
42536     function drawPointLabels(selection$$1, entities, filter, classes, labels) {
42537         var texts = selection$$1.selectAll('text.' + classes)
42538             .filter(filter)
42539             .data(entities, osmEntity$$1.key);
42540
42541         texts.exit()
42542             .remove();
42543
42544         texts = texts.enter()
42545             .append('text')
42546             .attr('class', function(d, i) {
42547                 return classes + ' ' + labels[i].classes + ' ' + d.id;
42548             })
42549             .merge(texts);
42550
42551         texts
42552             .attr('x', get(labels, 'x'))
42553             .attr('y', get(labels, 'y'))
42554             .style('text-anchor', get(labels, 'textAnchor'))
42555             .text(utilDisplayName)
42556             .each(function(d, i) {
42557                 textWidth(utilDisplayName(d), labels[i].height, this);
42558             });
42559     }
42560
42561
42562     function drawAreaLabels(selection$$1, entities, filter, classes, labels) {
42563         entities = entities.filter(hasText);
42564         labels = labels.filter(hasText);
42565         drawPointLabels(selection$$1, entities, filter, classes, labels);
42566
42567         function hasText(d, i) {
42568             return labels[i].hasOwnProperty('x') && labels[i].hasOwnProperty('y');
42569         }
42570     }
42571
42572
42573     function drawAreaIcons(selection$$1, entities, filter, classes, labels) {
42574         var icons = selection$$1.selectAll('use')
42575             .filter(filter)
42576             .data(entities, osmEntity$$1.key);
42577
42578         icons.exit()
42579             .remove();
42580
42581         icons = icons.enter()
42582             .append('use')
42583             .attr('class', 'icon areaicon')
42584             .attr('width', '18px')
42585             .attr('height', '18px')
42586             .merge(icons);
42587
42588         icons
42589             .attr('transform', get(labels, 'transform'))
42590             .attr('xlink:href', function(d) {
42591                 var icon = context.presets().match(d, context.graph()).icon;
42592                 return '#' + icon + (icon === 'hairdresser' ? '-24': '-18');    // workaround: maki hairdresser-18 broken?
42593             });
42594     }
42595
42596
42597     function drawCollisionBoxes(selection$$1, rtree, which) {
42598         var showDebug = context.getDebug('collision'),
42599             classes = 'debug ' + which + ' ' +
42600                 (which === 'debug-skipped' ? 'orange' : 'yellow');
42601
42602         var debug = selection$$1.selectAll('.layer-label-debug')
42603                 .data(showDebug ? [true] : []);
42604
42605         debug.exit()
42606             .remove();
42607
42608         debug = debug.enter()
42609             .append('g')
42610             .attr('class', 'layer-label-debug')
42611             .merge(debug);
42612
42613         if (showDebug) {
42614             var gj = rtree.all().map(function(d) {
42615                 return { type: 'Polygon', coordinates: [[
42616                     [d.minX, d.minY],
42617                     [d.maxX, d.minY],
42618                     [d.maxX, d.maxY],
42619                     [d.minX, d.maxY],
42620                     [d.minX, d.minY]
42621                 ]]};
42622             });
42623
42624             var debugboxes = debug.selectAll('.' + which)
42625                 .data(gj);
42626
42627             debugboxes.exit()
42628                 .remove();
42629
42630             debugboxes = debugboxes.enter()
42631                 .append('path')
42632                 .attr('class', classes)
42633                 .merge(debugboxes);
42634
42635             debugboxes
42636                 .attr('d', index$5());
42637         }
42638     }
42639
42640
42641     function drawLabels(selection$$1, graph, entities, filter, dimensions, fullRedraw) {
42642         var hidePoints = !selection$$1.selectAll('.node.point').node();
42643
42644         var labelable = [], i, j, k, entity;
42645         for (i = 0; i < labelStack.length; i++) {
42646             labelable.push([]);
42647         }
42648
42649         if (fullRedraw) {
42650             rdrawn.clear();
42651             rskipped.clear();
42652             entitybboxes = {};
42653         } else {
42654             for (i = 0; i < entities.length; i++) {
42655                 entity = entities[i];
42656                 var toRemove = []
42657                     .concat(entitybboxes[entity.id] || [])
42658                     .concat(entitybboxes[entity.id + 'I'] || []);
42659
42660                 for (j = 0; j < toRemove.length; j++) {
42661                     rdrawn.remove(toRemove[j]);
42662                     rskipped.remove(toRemove[j]);
42663                 }
42664             }
42665         }
42666
42667         // Split entities into groups specified by labelStack
42668         for (i = 0; i < entities.length; i++) {
42669             entity = entities[i];
42670             var geometry = entity.geometry(graph);
42671
42672             if (geometry === 'vertex')
42673                 continue;
42674             if (hidePoints && geometry === 'point')
42675                 continue;
42676
42677             var preset = geometry === 'area' && context.presets().match(entity, graph),
42678                 icon = preset && !blacklisted(preset) && preset.icon;
42679
42680             if (!icon && !utilDisplayName(entity))
42681                 continue;
42682
42683             for (k = 0; k < labelStack.length; k++) {
42684                 var matchGeom = labelStack[k][0],
42685                     matchKey = labelStack[k][1],
42686                     matchVal = labelStack[k][2],
42687                     hasVal = entity.tags[matchKey];
42688
42689                 if (geometry === matchGeom && hasVal && (matchVal === '*' || matchVal === hasVal)) {
42690                     labelable[k].push(entity);
42691                     break;
42692                 }
42693             }
42694         }
42695
42696         var positions = {
42697             point: [],
42698             line: [],
42699             area: []
42700         };
42701
42702         var labelled = {
42703             point: [],
42704             line: [],
42705             area: []
42706         };
42707
42708         // Try and find a valid label for labellable entities
42709         for (k = 0; k < labelable.length; k++) {
42710             var fontSize = labelStack[k][3];
42711             for (i = 0; i < labelable[k].length; i++) {
42712                 entity = labelable[k][i];
42713                 var name = utilDisplayName(entity),
42714                     width = name && textWidth(name, fontSize),
42715                     p;
42716                 if (entity.geometry(graph) === 'point') {
42717                     p = getPointLabel(entity, width, fontSize);
42718                 } else if (entity.geometry(graph) === 'line') {
42719                     p = getLineLabel(entity, width, fontSize);
42720                 } else if (entity.geometry(graph) === 'area') {
42721                     p = getAreaLabel(entity, width, fontSize);
42722                 }
42723                 if (p) {
42724                     p.classes = entity.geometry(graph) + ' tag-' + labelStack[k][1];
42725                     positions[entity.geometry(graph)].push(p);
42726                     labelled[entity.geometry(graph)].push(entity);
42727                 }
42728             }
42729         }
42730
42731
42732         function getPointLabel(entity, width, height) {
42733             var pointOffsets = {
42734                     ltr: [15, -12, 'start'],
42735                     rtl: [-15, -12, 'end']
42736                 };
42737
42738             var coord = projection(entity.loc),
42739                 margin = 2,
42740                 textDirection = detected.textDirection,
42741                 offset = pointOffsets[textDirection],
42742                 p = {
42743                     height: height,
42744                     width: width,
42745                     x: coord[0] + offset[0],
42746                     y: coord[1] + offset[1],
42747                     textAnchor: offset[2]
42748                 },
42749                 bbox;
42750
42751             if (textDirection === 'rtl') {
42752                 bbox = {
42753                     minX: p.x - width - margin,
42754                     minY: p.y - (height / 2) - margin,
42755                     maxX: p.x + margin,
42756                     maxY: p.y + (height / 2) + margin
42757                 };
42758             } else {
42759                 bbox = {
42760                     minX: p.x - margin,
42761                     minY: p.y - (height / 2) - margin,
42762                     maxX: p.x + width + margin,
42763                     maxY: p.y + (height / 2) + margin
42764                 };
42765             }
42766
42767             if (tryInsert([bbox], entity.id, true)) {
42768                 return p;
42769             }
42770         }
42771
42772
42773         function getLineLabel(entity, width, height) {
42774             var viewport = geoExtent$$1(context.projection.clipExtent()).polygon(),
42775                 nodes = lodash.map(graph.childNodes(entity), 'loc').map(projection),
42776                 length = geoPathLength(nodes);
42777
42778             if (length < width + 20) return;
42779
42780             // % along the line to attempt to place the label
42781             var lineOffsets = [50, 45, 55, 40, 60, 35, 65, 30, 70,
42782                                25, 75, 20, 80, 15, 95, 10, 90, 5, 95];
42783             var margin = 3;
42784
42785             for (var i = 0; i < lineOffsets.length; i++) {
42786                 var offset = lineOffsets[i],
42787                     middle = offset / 100 * length,
42788                     start = middle - width / 2;
42789
42790                 if (start < 0 || start + width > length) continue;
42791
42792                 // generate subpath and ignore paths that are invalid or don't cross viewport.
42793                 var sub = subpath(nodes, start, start + width);
42794                 if (!sub || !geoPolygonIntersectsPolygon(viewport, sub, true)) {
42795                     continue;
42796                 }
42797
42798                 var isReverse = reverse(sub);
42799                 if (isReverse) {
42800                     sub = sub.reverse();
42801                 }
42802
42803                 var bboxes = [],
42804                     boxsize = (height + 2) / 2;
42805
42806                 for (var j = 0; j < sub.length - 1; j++) {
42807                     var a = sub[j];
42808                     var b = sub[j + 1];
42809                     var num = Math.max(1, Math.floor(geoEuclideanDistance(a, b) / boxsize / 2));
42810
42811                     for (var box = 0; box < num; box++) {
42812                         var p = geoInterp(a, b, box / num);
42813                         var x0 = p[0] - boxsize - margin;
42814                         var y0 = p[1] - boxsize - margin;
42815                         var x1 = p[0] + boxsize + margin;
42816                         var y1 = p[1] + boxsize + margin;
42817
42818                         bboxes.push({
42819                             minX: Math.min(x0, x1),
42820                             minY: Math.min(y0, y1),
42821                             maxX: Math.max(x0, x1),
42822                             maxY: Math.max(y0, y1)
42823                         });
42824                     }
42825                 }
42826
42827                 if (tryInsert(bboxes, entity.id, false)) {
42828                     return {
42829                         'font-size': height + 2,
42830                         lineString: lineString(sub),
42831                         startOffset: offset + '%'
42832                     };
42833                 }
42834             }
42835
42836             function reverse(p) {
42837                 var angle = Math.atan2(p[1][1] - p[0][1], p[1][0] - p[0][0]);
42838                 return !(p[0][0] < p[p.length - 1][0] && angle < Math.PI/2 && angle > -Math.PI/2);
42839             }
42840
42841             function lineString(nodes) {
42842                 return 'M' + nodes.join('L');
42843             }
42844
42845             function subpath(nodes, from, to) {
42846                 var sofar = 0,
42847                     start, end, i0, i1;
42848
42849                 for (var i = 0; i < nodes.length - 1; i++) {
42850                     var a = nodes[i],
42851                         b = nodes[i + 1];
42852                     var current = geoEuclideanDistance(a, b);
42853                     var portion;
42854                     if (!start && sofar + current >= from) {
42855                         portion = (from - sofar) / current;
42856                         start = [
42857                             a[0] + portion * (b[0] - a[0]),
42858                             a[1] + portion * (b[1] - a[1])
42859                         ];
42860                         i0 = i + 1;
42861                     }
42862                     if (!end && sofar + current >= to) {
42863                         portion = (to - sofar) / current;
42864                         end = [
42865                             a[0] + portion * (b[0] - a[0]),
42866                             a[1] + portion * (b[1] - a[1])
42867                         ];
42868                         i1 = i + 1;
42869                     }
42870                     sofar += current;
42871                 }
42872
42873                 var ret = nodes.slice(i0, i1);
42874                 ret.unshift(start);
42875                 ret.push(end);
42876                 return ret;
42877             }
42878         }
42879
42880
42881         function getAreaLabel(entity, width, height) {
42882             var centroid = path$$1.centroid(entity.asGeoJSON(graph, true)),
42883                 extent$$1 = entity.extent(graph),
42884                 entitywidth = projection(extent$$1[1])[0] - projection(extent$$1[0])[0];
42885
42886             if (isNaN(centroid[0]) || entitywidth < 20) return;
42887
42888             var iconSize = 18,
42889                 iconX = centroid[0] - (iconSize / 2),
42890                 iconY = centroid[1] - (iconSize / 2),
42891                 margin = 2,
42892                 textOffset = iconSize + margin,
42893                 p = { transform: 'translate(' + iconX + ',' + iconY + ')' };
42894
42895             var bbox = {
42896                 minX: iconX,
42897                 minY: iconY,
42898                 maxX: iconX + iconSize,
42899                 maxY: iconY + iconSize
42900             };
42901
42902             // try to add icon
42903             if (tryInsert([bbox], entity.id + 'I', true)) {
42904                 if (width && entitywidth >= width + 20) {
42905                     var labelX = centroid[0],
42906                         labelY = centroid[1] + textOffset;
42907
42908                     bbox = {
42909                         minX: labelX - (width / 2) - margin,
42910                         minY: labelY - (height / 2) - margin,
42911                         maxX: labelX + (width / 2) + margin,
42912                         maxY: labelY + (height / 2) + margin
42913                     };
42914
42915                     // try to add label
42916                     if (tryInsert([bbox], entity.id, true)) {
42917                         p.x = labelX;
42918                         p.y = labelY;
42919                         p.textAnchor = 'middle';
42920                         p.height = height;
42921                     }
42922                 }
42923
42924                 return p;
42925             }
42926         }
42927
42928
42929         function tryInsert(bboxes, id, saveSkipped) {
42930             var skipped = false,
42931                 bbox;
42932
42933             for (var i = 0; i < bboxes.length; i++) {
42934                 bbox = bboxes[i];
42935                 bbox.id = id;
42936
42937                 // Check that label is visible
42938                 if (bbox.minX < 0 || bbox.minY < 0 || bbox.maxX > dimensions[0] || bbox.maxY > dimensions[1]) {
42939                     skipped = true;
42940                     break;
42941                 }
42942                 if (rdrawn.collides(bbox)) {
42943                     skipped = true;
42944                     break;
42945                 }
42946             }
42947
42948             entitybboxes[id] = bboxes;
42949
42950             if (skipped) {
42951                 if (saveSkipped) {
42952                     rskipped.load(bboxes);
42953                 }
42954             } else {
42955                 rdrawn.load(bboxes);
42956             }
42957
42958             return !skipped;
42959         }
42960
42961
42962         var label = selection$$1.selectAll('.layer-label'),
42963             halo = selection$$1.selectAll('.layer-halo');
42964
42965         // points
42966         drawPointLabels(label, labelled.point, filter, 'pointlabel', positions.point);
42967         drawPointLabels(halo, labelled.point, filter, 'pointlabel-halo', positions.point);
42968
42969         // lines
42970         drawLinePaths(halo, labelled.line, filter, '', positions.line);
42971         drawLineLabels(label, labelled.line, filter, 'linelabel', positions.line);
42972         drawLineLabels(halo, labelled.line, filter, 'linelabel-halo', positions.line);
42973
42974         // areas
42975         drawAreaLabels(label, labelled.area, filter, 'arealabel', positions.area);
42976         drawAreaLabels(halo, labelled.area, filter, 'arealabel-halo', positions.area);
42977         drawAreaIcons(label, labelled.area, filter, 'arealabel-icon', positions.area);
42978
42979         // debug
42980         drawCollisionBoxes(label, rskipped, 'debug-skipped');
42981         drawCollisionBoxes(label, rdrawn, 'debug-drawn');
42982     }
42983
42984
42985     function hideOnMouseover() {
42986         if (event.buttons) return;
42987
42988         var layers = select(this)
42989             .selectAll('.layer-label, .layer-halo');
42990
42991         layers.selectAll('.proximate')
42992             .classed('proximate', false);
42993
42994         var mouse$$1 = context.mouse(),
42995             pad = 20,
42996             bbox = { minX: mouse$$1[0] - pad, minY: mouse$$1[1] - pad, maxX: mouse$$1[0] + pad, maxY: mouse$$1[1] + pad },
42997             ids = lodash.map(rdrawn.search(bbox), 'id');
42998
42999         layers.selectAll(utilEntitySelector(ids))
43000             .classed('proximate', true);
43001     }
43002
43003
43004     drawLabels.observe = function(selection$$1) {
43005         selection$$1.on('mousemove.hidelabels', hideOnMouseover);
43006     };
43007
43008
43009     drawLabels.off = function(selection$$1) {
43010         selection$$1.on('mousemove.hidelabels', null);
43011     };
43012
43013
43014     return drawLabels;
43015 }
43016
43017 // Copies a variable number of methods from source to target.
43018 function utilRebind(target, source) {
43019     var i = 1, n = arguments.length, method;
43020     while (++i < n) {
43021         target[method = arguments[i]] = d3_rebind(target, source, source[method]);
43022     }
43023     return target;
43024 }
43025
43026 // Method is assumed to be a standard D3 getter-setter:
43027 // If passed with no arguments, gets the value.
43028 // If passed with arguments, sets the value and returns the target.
43029 function d3_rebind(target, source, method) {
43030     return function() {
43031         var value = method.apply(source, arguments);
43032         return value === source ? target : value;
43033     };
43034 }
43035
43036 function refresh(selection, node) {
43037     var cr = node.getBoundingClientRect();
43038     var prop = [cr.width, cr.height];
43039     selection.property('__dimensions__', prop);
43040     return prop;
43041 }
43042
43043 function utilGetDimensions(selection, force) {
43044     if (!selection || selection.empty()) {
43045         return [0, 0];
43046     }
43047     var node = selection.node(),
43048         cached = selection.property('__dimensions__');
43049     return (!cached || force) ? refresh(selection, node) : cached;
43050 }
43051
43052
43053 function utilSetDimensions(selection, dimensions) {
43054     if (!selection || selection.empty()) {
43055         return selection;
43056     }
43057     var node = selection.node();
43058     if (dimensions === null) {
43059         refresh(selection, node);
43060         return selection;
43061     }
43062     return selection
43063         .property('__dimensions__', [dimensions[0], dimensions[1]])
43064         .attr('width', dimensions[0])
43065         .attr('height', dimensions[1]);
43066 }
43067
43068 function svgPointTransform(projection) {
43069     return function(entity) {
43070         // http://jsperf.com/short-array-join
43071         var pt = projection(entity.loc);
43072         return 'translate(' + pt[0] + ',' + pt[1] + ')';
43073     };
43074 }
43075
43076 function d3geoTile() {
43077   var size = [960, 500],
43078       scale = 256,
43079       scaleExtent = [0, 20],
43080       translate = [size[0] / 2, size[1] / 2],
43081       zoomDelta = 0;
43082
43083   function bound(_) {
43084       return Math.min(scaleExtent[1], Math.max(scaleExtent[0], _));
43085   }
43086
43087   function tile() {
43088     var z = Math.max(Math.log(scale) / Math.LN2 - 8, 0),
43089         z0 = bound(Math.round(z + zoomDelta)),
43090         k = Math.pow(2, z - z0 + 8),
43091         origin = [(translate[0] - scale / 2) / k, (translate[1] - scale / 2) / k],
43092         tiles = [],
43093         cols = range(Math.max(0, Math.floor(-origin[0])), Math.max(0, Math.ceil(size[0] / k - origin[0]))),
43094         rows = range(Math.max(0, Math.floor(-origin[1])), Math.max(0, Math.ceil(size[1] / k - origin[1])));
43095
43096     rows.forEach(function(y) {
43097       cols.forEach(function(x) {
43098         tiles.push([x, y, z0]);
43099       });
43100     });
43101
43102     tiles.translate = origin;
43103     tiles.scale = k;
43104
43105     return tiles;
43106   }
43107
43108   tile.scaleExtent = function(_) {
43109     if (!arguments.length) return scaleExtent;
43110     scaleExtent = _;
43111     return tile;
43112   };
43113
43114   tile.size = function(_) {
43115     if (!arguments.length) return size;
43116     size = _;
43117     return tile;
43118   };
43119
43120   tile.scale = function(_) {
43121     if (!arguments.length) return scale;
43122     scale = _;
43123     return tile;
43124   };
43125
43126   tile.translate = function(_) {
43127     if (!arguments.length) return translate;
43128     translate = _;
43129     return tile;
43130   };
43131
43132   tile.zoomDelta = function(_) {
43133     if (!arguments.length) return zoomDelta;
43134     zoomDelta = +_;
43135     return tile;
43136   };
43137
43138   return tile;
43139 }
43140
43141 /* global Mapillary:false */
43142 var apibase = 'https://a.mapillary.com/v2/';
43143 var viewercss = 'mapillary-js/mapillary.min.css';
43144 var viewerjs = 'mapillary-js/mapillary.min.js';
43145 var trafficocss = 'traffico/stylesheets/traffico.css';
43146 var clientId = 'NzNRM2otQkR2SHJzaXJmNmdQWVQ0dzo1ZWYyMmYwNjdmNDdlNmVi';
43147 var maxResults = 1000;
43148 var maxPages = 10;
43149 var tileZoom = 14;
43150 var dispatch$2 = dispatch('loadedImages', 'loadedSigns');
43151 var mapillaryCache;
43152 var mapillaryClicks;
43153 var mapillaryImage;
43154 var mapillarySignDefs;
43155 var mapillaryViewer;
43156
43157
43158 function abortRequest(i) {
43159     i.abort();
43160 }
43161
43162
43163 function nearNullIsland(x, y, z) {
43164     if (z >= 7) {
43165         var center = Math.pow(2, z - 1),
43166             width = Math.pow(2, z - 6),
43167             min$$1 = center - (width / 2),
43168             max$$1 = center + (width / 2) - 1;
43169         return x >= min$$1 && x <= max$$1 && y >= min$$1 && y <= max$$1;
43170     }
43171     return false;
43172 }
43173
43174
43175 function getTiles(projection) {
43176     var s = projection.scale() * 2 * Math.PI,
43177         z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
43178         ts = 256 * Math.pow(2, z - tileZoom),
43179         origin = [
43180             s / 2 - projection.translate()[0],
43181             s / 2 - projection.translate()[1]];
43182
43183     return d3geoTile()
43184         .scaleExtent([tileZoom, tileZoom])
43185         .scale(s)
43186         .size(projection.clipExtent()[1])
43187         .translate(projection.translate())()
43188         .map(function(tile) {
43189             var x = tile[0] * ts - origin[0],
43190                 y = tile[1] * ts - origin[1];
43191
43192             return {
43193                 id: tile.toString(),
43194                 extent: geoExtent$$1(
43195                     projection.invert([x, y + ts]),
43196                     projection.invert([x + ts, y])
43197                 )
43198             };
43199         });
43200 }
43201
43202
43203 function loadTiles(which, url, projection) {
43204     var tiles = getTiles(projection).filter(function(t) {
43205           var xyz = t.id.split(',');
43206           return !nearNullIsland(xyz[0], xyz[1], xyz[2]);
43207         });
43208
43209     lodash.filter(which.inflight, function(v, k) {
43210         var wanted = lodash.find(tiles, function(tile) { return k === (tile.id + ',0'); });
43211         if (!wanted) delete which.inflight[k];
43212         return !wanted;
43213     }).map(abortRequest);
43214
43215     tiles.forEach(function(tile) {
43216         loadTilePage(which, url, tile, 0);
43217     });
43218 }
43219
43220
43221 function loadTilePage(which, url, tile, page) {
43222     var cache = mapillaryCache[which],
43223         id = tile.id + ',' + String(page),
43224         rect = tile.extent.rectangle();
43225
43226     if (cache.loaded[id] || cache.inflight[id]) return;
43227
43228     cache.inflight[id] = json(url +
43229         utilQsString({
43230             geojson: 'true',
43231             limit: maxResults,
43232             page: page,
43233             client_id: clientId,
43234             min_lon: rect[0],
43235             min_lat: rect[1],
43236             max_lon: rect[2],
43237             max_lat: rect[3]
43238         }), function(err, data) {
43239             cache.loaded[id] = true;
43240             delete cache.inflight[id];
43241             if (err || !data.features || !data.features.length) return;
43242
43243             var features = [],
43244                 nextPage = page + 1,
43245                 feature, loc, d;
43246
43247             for (var i = 0; i < data.features.length; i++) {
43248                 feature = data.features[i];
43249                 loc = feature.geometry.coordinates;
43250                 d = { key: feature.properties.key, loc: loc };
43251                 if (which === 'images') d.ca = feature.properties.ca;
43252                 if (which === 'signs') d.signs = feature.properties.rects;
43253
43254                 features.push({minX: loc[0], minY: loc[1], maxX: loc[0], maxY: loc[1], data: d});
43255             }
43256
43257             cache.rtree.load(features);
43258
43259             if (which === 'images') dispatch$2.call('loadedImages');
43260             if (which === 'signs') dispatch$2.call('loadedSigns');
43261
43262             if (data.features.length === maxResults && nextPage < maxPages) {
43263                 loadTilePage(which, url, tile, nextPage);
43264             }
43265         }
43266     );
43267 }
43268
43269
43270 // partition viewport into `psize` x `psize` regions
43271 function partitionViewport(psize, projection) {
43272     var dimensions = projection.clipExtent()[1];
43273     psize = psize || 16;
43274     var cols = range(0, dimensions[0], psize),
43275         rows = range(0, dimensions[1], psize),
43276         partitions = [];
43277
43278     rows.forEach(function(y) {
43279         cols.forEach(function(x) {
43280             var min$$1 = [x, y + psize],
43281                 max$$1 = [x + psize, y];
43282             partitions.push(
43283                 geoExtent$$1(projection.invert(min$$1), projection.invert(max$$1)));
43284         });
43285     });
43286
43287     return partitions;
43288 }
43289
43290
43291 // no more than `limit` results per partition.
43292 function searchLimited(psize, limit, projection, rtree) {
43293     limit = limit || 3;
43294
43295     var partitions = partitionViewport(psize, projection);
43296     return lodash.flatten(lodash.compact(lodash.map(partitions, function(extent$$1) {
43297         return rtree.search(extent$$1.bbox())
43298             .slice(0, limit)
43299             .map(function(d) { return d.data; });
43300     })));
43301 }
43302
43303
43304
43305 var serviceMapillary = {
43306
43307     init: function() {
43308         if (!mapillaryCache) {
43309             this.reset();
43310         }
43311
43312         this.event = utilRebind(this, dispatch$2, 'on');
43313     },
43314
43315     reset: function() {
43316         var cache = mapillaryCache;
43317
43318         if (cache) {
43319             if (cache.images && cache.images.inflight) {
43320                 lodash.forEach(cache.images.inflight, abortRequest);
43321             }
43322             if (cache.signs && cache.signs.inflight) {
43323                 lodash.forEach(cache.signs.inflight, abortRequest);
43324             }
43325         }
43326
43327         mapillaryCache = {
43328             images: { inflight: {}, loaded: {}, rtree: index$8() },
43329             signs:  { inflight: {}, loaded: {}, rtree: index$8() }
43330         };
43331
43332         mapillaryImage = null;
43333         mapillaryClicks = [];
43334     },
43335
43336
43337     images: function(projection) {
43338         var psize = 16, limit = 3;
43339         return searchLimited(psize, limit, projection, mapillaryCache.images.rtree);
43340     },
43341
43342
43343     signs: function(projection) {
43344         var psize = 32, limit = 3;
43345         return searchLimited(psize, limit, projection, mapillaryCache.signs.rtree);
43346     },
43347
43348
43349     signsSupported: function() {
43350         var detected = utilDetect();
43351         if (detected.ie) return false;
43352         if ((detected.browser.toLowerCase() === 'safari') && (parseFloat(detected.version) < 10)) return false;
43353         return true;
43354     },
43355
43356
43357     signHTML: function(d) {
43358         if (!mapillarySignDefs) return;
43359
43360         var detectionPackage = d.signs[0].package,
43361             type = d.signs[0].type,
43362             country = detectionPackage.split('_')[1];
43363
43364         return mapillarySignDefs[country][type];
43365     },
43366
43367
43368     loadImages: function(projection) {
43369         var url = apibase + 'search/im/geojson?';
43370         loadTiles('images', url, projection);
43371     },
43372
43373
43374     loadSigns: function(context, projection) {
43375         var url = apibase + 'search/im/geojson/or?';
43376         loadTiles('signs', url, projection);
43377
43378         // load traffico css
43379         select('head').selectAll('#traffico')
43380             .data([0])
43381             .enter()
43382             .append('link')
43383             .attr('id', 'traffico')
43384             .attr('rel', 'stylesheet')
43385             .attr('href', context.asset(trafficocss));
43386
43387         // load traffico sign defs
43388         if (!mapillarySignDefs) {
43389             mapillarySignDefs = {};
43390             lodash.each(['au', 'br', 'ca', 'de', 'us'], function(region) {
43391                 json(context.asset('traffico/string-maps/' + region + '-map.json'), function(err, data) {
43392                     if (err) return;
43393                     if (region === 'de') region = 'eu';
43394                     mapillarySignDefs[region] = data;
43395                 });
43396             });
43397         }
43398     },
43399
43400
43401     loadViewer: function(context) {
43402         var that = this;
43403         var wrap = select('#content').selectAll('.mapillary-wrap')
43404             .data([0]);
43405
43406         var enter = wrap.enter()
43407             .append('div')
43408             .attr('class', 'mapillary-wrap')
43409             .classed('al', true)       // 'al'=left,  'ar'=right
43410             .classed('hidden', true);
43411
43412         enter
43413             .append('button')
43414             .attr('class', 'thumb-hide')
43415             .on('click', function () { that.hideViewer(); })
43416             .append('div')
43417             .call(svgIcon('#icon-close'));
43418
43419         enter
43420             .append('div')
43421             .attr('id', 'mly')
43422             .attr('class', 'mly-wrapper')
43423             .classed('active', false);
43424
43425         // load mapillary-viewercss
43426         select('head').selectAll('#mapillary-viewercss')
43427             .data([0])
43428             .enter()
43429             .append('link')
43430             .attr('id', 'mapillary-viewercss')
43431             .attr('rel', 'stylesheet')
43432             .attr('href', context.asset(viewercss));
43433
43434         // load mapillary-viewerjs
43435         select('head').selectAll('#mapillary-viewerjs')
43436             .data([0])
43437             .enter()
43438             .append('script')
43439             .attr('id', 'mapillary-viewerjs')
43440             .attr('src', context.asset(viewerjs));
43441     },
43442
43443
43444     showViewer: function() {
43445         select('#content')
43446             .selectAll('.mapillary-wrap')
43447             .classed('hidden', false)
43448             .selectAll('.mly-wrapper')
43449             .classed('active', true);
43450
43451         return this;
43452     },
43453
43454
43455     hideViewer: function() {
43456         select('#content')
43457             .selectAll('.mapillary-wrap')
43458             .classed('hidden', true)
43459             .selectAll('.mly-wrapper')
43460             .classed('active', false);
43461
43462         selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
43463             .classed('selected', false);
43464
43465         mapillaryImage = null;
43466         return this;
43467     },
43468
43469
43470     updateViewer: function(imageKey, context) {
43471         if (!imageKey) return;
43472
43473         if (!mapillaryViewer) {
43474             this.initViewer(imageKey, context);
43475         } else {
43476             mapillaryViewer.moveToKey(imageKey);
43477         }
43478
43479         return this;
43480     },
43481
43482
43483     initViewer: function(imageKey, context) {
43484         var that = this;
43485         if (Mapillary && imageKey) {
43486             var opts = {
43487                 baseImageSize: 320,
43488                 component: {
43489                     cover: false,
43490                     keyboard: false
43491                 }
43492             };
43493
43494             mapillaryViewer = new Mapillary.Viewer('mly', clientId, imageKey, opts);
43495             mapillaryViewer.on('nodechanged', nodeChanged);
43496         }
43497
43498         function nodeChanged(node) {
43499             var clicks = mapillaryClicks;
43500             var index = clicks.indexOf(node.key);
43501             if (index > -1) {    // nodechange initiated from clicking on a marker..
43502                 clicks.splice(index, 1);
43503             } else {             // nodechange initiated from the Mapillary viewer controls..
43504                 var loc = node.computedLatLon ? [node.computedLatLon.lon, node.computedLatLon.lat] : [node.latLon.lon, node.latLon.lat];
43505                 context.map().centerEase(loc);
43506                 that.selectedImage(node.key, false);
43507             }
43508         }
43509     },
43510
43511
43512     selectedImage: function(imageKey, fromClick) {
43513         if (!arguments.length) return mapillaryImage;
43514
43515         mapillaryImage = imageKey;
43516         if (fromClick) {
43517             mapillaryClicks.push(imageKey);
43518         }
43519
43520         selectAll('.layer-mapillary-images .viewfield-group, .layer-mapillary-signs .icon-sign')
43521             .classed('selected', function(d) { return d.key === imageKey; });
43522
43523         return this;
43524     },
43525
43526
43527     cache: function(_) {
43528         if (!arguments.length) return mapillaryCache;
43529         mapillaryCache = _;
43530         return this;
43531     },
43532
43533
43534     signDefs: function(_) {
43535         if (!arguments.length) return mapillarySignDefs;
43536         mapillarySignDefs = _;
43537         return this;
43538     }
43539
43540 };
43541
43542 var endpoint = 'https://nominatim.openstreetmap.org/reverse?';
43543 var nominatimCache;
43544
43545
43546 var serviceNominatim = {
43547
43548     init: function() { nominatimCache = index$8(); },
43549     reset: function() { nominatimCache = index$8(); },
43550
43551
43552     countryCode: function (location, callback) {
43553         var countryCodes = nominatimCache.search(
43554             { minX: location[0], minY: location[1], maxX: location[0], maxY: location[1] }
43555         );
43556
43557         if (countryCodes.length > 0) {
43558             return callback(null, countryCodes[0].data);
43559         }
43560
43561         json(endpoint +
43562             utilQsString({
43563                 format: 'json',
43564                 addressdetails: 1,
43565                 lat: location[1],
43566                 lon: location[0]
43567             }), function(err, result) {
43568                 if (err)
43569                     return callback(err);
43570                 else if (result && result.error)
43571                     return callback(result.error);
43572
43573                 var extent$$1 = geoExtent$$1(location).padByMeters(1000);
43574                 nominatimCache.insert(Object.assign(extent$$1.bbox(),
43575                     { data: result.address.country_code }
43576                 ));
43577
43578                 callback(null, result.address.country_code);
43579             }
43580         );
43581     }
43582
43583 };
43584
43585 var hashes$1 = createCommonjsModule(function (module, exports) {
43586 /**
43587  * jshashes - https://github.com/h2non/jshashes
43588  * Released under the "New BSD" license
43589  *
43590  * Algorithms specification:
43591  *
43592  * MD5 - http://www.ietf.org/rfc/rfc1321.txt
43593  * RIPEMD-160 - http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
43594  * SHA1   - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
43595  * SHA256 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
43596  * SHA512 - http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
43597  * HMAC - http://www.ietf.org/rfc/rfc2104.txt
43598  */
43599 (function() {
43600   var Hashes;
43601
43602   function utf8Encode(str) {
43603     var x, y, output = '',
43604       i = -1,
43605       l;
43606
43607     if (str && str.length) {
43608       l = str.length;
43609       while ((i += 1) < l) {
43610         /* Decode utf-16 surrogate pairs */
43611         x = str.charCodeAt(i);
43612         y = i + 1 < l ? str.charCodeAt(i + 1) : 0;
43613         if (0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) {
43614           x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF);
43615           i += 1;
43616         }
43617         /* Encode output as utf-8 */
43618         if (x <= 0x7F) {
43619           output += String.fromCharCode(x);
43620         } else if (x <= 0x7FF) {
43621           output += String.fromCharCode(0xC0 | ((x >>> 6) & 0x1F),
43622             0x80 | (x & 0x3F));
43623         } else if (x <= 0xFFFF) {
43624           output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F),
43625             0x80 | ((x >>> 6) & 0x3F),
43626             0x80 | (x & 0x3F));
43627         } else if (x <= 0x1FFFFF) {
43628           output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07),
43629             0x80 | ((x >>> 12) & 0x3F),
43630             0x80 | ((x >>> 6) & 0x3F),
43631             0x80 | (x & 0x3F));
43632         }
43633       }
43634     }
43635     return output;
43636   }
43637
43638   function utf8Decode(str) {
43639     var i, ac, c1, c2, c3, arr = [],
43640       l;
43641     i = ac = c1 = c2 = c3 = 0;
43642
43643     if (str && str.length) {
43644       l = str.length;
43645       str += '';
43646
43647       while (i < l) {
43648         c1 = str.charCodeAt(i);
43649         ac += 1;
43650         if (c1 < 128) {
43651           arr[ac] = String.fromCharCode(c1);
43652           i += 1;
43653         } else if (c1 > 191 && c1 < 224) {
43654           c2 = str.charCodeAt(i + 1);
43655           arr[ac] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
43656           i += 2;
43657         } else {
43658           c2 = str.charCodeAt(i + 1);
43659           c3 = str.charCodeAt(i + 2);
43660           arr[ac] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
43661           i += 3;
43662         }
43663       }
43664     }
43665     return arr.join('');
43666   }
43667
43668   /**
43669    * Add integers, wrapping at 2^32. This uses 16-bit operations internally
43670    * to work around bugs in some JS interpreters.
43671    */
43672
43673   function safe_add(x, y) {
43674     var lsw = (x & 0xFFFF) + (y & 0xFFFF),
43675       msw = (x >> 16) + (y >> 16) + (lsw >> 16);
43676     return (msw << 16) | (lsw & 0xFFFF);
43677   }
43678
43679   /**
43680    * Bitwise rotate a 32-bit number to the left.
43681    */
43682
43683   function bit_rol(num, cnt) {
43684     return (num << cnt) | (num >>> (32 - cnt));
43685   }
43686
43687   /**
43688    * Convert a raw string to a hex string
43689    */
43690
43691   function rstr2hex(input, hexcase) {
43692     var hex_tab = hexcase ? '0123456789ABCDEF' : '0123456789abcdef',
43693       output = '',
43694       x, i = 0,
43695       l = input.length;
43696     for (; i < l; i += 1) {
43697       x = input.charCodeAt(i);
43698       output += hex_tab.charAt((x >>> 4) & 0x0F) + hex_tab.charAt(x & 0x0F);
43699     }
43700     return output;
43701   }
43702
43703   /**
43704    * Encode a string as utf-16
43705    */
43706
43707   function str2rstr_utf16le(input) {
43708     var i, l = input.length,
43709       output = '';
43710     for (i = 0; i < l; i += 1) {
43711       output += String.fromCharCode(input.charCodeAt(i) & 0xFF, (input.charCodeAt(i) >>> 8) & 0xFF);
43712     }
43713     return output;
43714   }
43715
43716   function str2rstr_utf16be(input) {
43717     var i, l = input.length,
43718       output = '';
43719     for (i = 0; i < l; i += 1) {
43720       output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, input.charCodeAt(i) & 0xFF);
43721     }
43722     return output;
43723   }
43724
43725   /**
43726    * Convert an array of big-endian words to a string
43727    */
43728
43729   function binb2rstr(input) {
43730     var i, l = input.length * 32,
43731       output = '';
43732     for (i = 0; i < l; i += 8) {
43733       output += String.fromCharCode((input[i >> 5] >>> (24 - i % 32)) & 0xFF);
43734     }
43735     return output;
43736   }
43737
43738   /**
43739    * Convert an array of little-endian words to a string
43740    */
43741
43742   function binl2rstr(input) {
43743     var i, l = input.length * 32,
43744       output = '';
43745     for (i = 0; i < l; i += 8) {
43746       output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
43747     }
43748     return output;
43749   }
43750
43751   /**
43752    * Convert a raw string to an array of little-endian words
43753    * Characters >255 have their high-byte silently ignored.
43754    */
43755
43756   function rstr2binl(input) {
43757     var i, l = input.length * 8,
43758       output = Array(input.length >> 2),
43759       lo = output.length;
43760     for (i = 0; i < lo; i += 1) {
43761       output[i] = 0;
43762     }
43763     for (i = 0; i < l; i += 8) {
43764       output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (i % 32);
43765     }
43766     return output;
43767   }
43768
43769   /**
43770    * Convert a raw string to an array of big-endian words
43771    * Characters >255 have their high-byte silently ignored.
43772    */
43773
43774   function rstr2binb(input) {
43775     var i, l = input.length * 8,
43776       output = Array(input.length >> 2),
43777       lo = output.length;
43778     for (i = 0; i < lo; i += 1) {
43779       output[i] = 0;
43780     }
43781     for (i = 0; i < l; i += 8) {
43782       output[i >> 5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32);
43783     }
43784     return output;
43785   }
43786
43787   /**
43788    * Convert a raw string to an arbitrary string encoding
43789    */
43790
43791   function rstr2any(input, encoding) {
43792     var divisor = encoding.length,
43793       remainders = Array(),
43794       i, q, x, ld, quotient, dividend, output, full_length;
43795
43796     /* Convert to an array of 16-bit big-endian values, forming the dividend */
43797     dividend = Array(Math.ceil(input.length / 2));
43798     ld = dividend.length;
43799     for (i = 0; i < ld; i += 1) {
43800       dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1);
43801     }
43802
43803     /**
43804      * Repeatedly perform a long division. The binary array forms the dividend,
43805      * the length of the encoding is the divisor. Once computed, the quotient
43806      * forms the dividend for the next step. We stop when the dividend is zerHashes.
43807      * All remainders are stored for later use.
43808      */
43809     while (dividend.length > 0) {
43810       quotient = Array();
43811       x = 0;
43812       for (i = 0; i < dividend.length; i += 1) {
43813         x = (x << 16) + dividend[i];
43814         q = Math.floor(x / divisor);
43815         x -= q * divisor;
43816         if (quotient.length > 0 || q > 0) {
43817           quotient[quotient.length] = q;
43818         }
43819       }
43820       remainders[remainders.length] = x;
43821       dividend = quotient;
43822     }
43823
43824     /* Convert the remainders to the output string */
43825     output = '';
43826     for (i = remainders.length - 1; i >= 0; i--) {
43827       output += encoding.charAt(remainders[i]);
43828     }
43829
43830     /* Append leading zero equivalents */
43831     full_length = Math.ceil(input.length * 8 / (Math.log(encoding.length) / Math.log(2)));
43832     for (i = output.length; i < full_length; i += 1) {
43833       output = encoding[0] + output;
43834     }
43835     return output;
43836   }
43837
43838   /**
43839    * Convert a raw string to a base-64 string
43840    */
43841
43842   function rstr2b64(input, b64pad) {
43843     var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
43844       output = '',
43845       len = input.length,
43846       i, j, triplet;
43847     b64pad = b64pad || '=';
43848     for (i = 0; i < len; i += 3) {
43849       triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
43850       for (j = 0; j < 4; j += 1) {
43851         if (i * 8 + j * 6 > input.length * 8) {
43852           output += b64pad;
43853         } else {
43854           output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F);
43855         }
43856       }
43857     }
43858     return output;
43859   }
43860
43861   Hashes = {
43862     /**
43863      * @property {String} version
43864      * @readonly
43865      */
43866     VERSION: '1.0.5',
43867     /**
43868      * @member Hashes
43869      * @class Base64
43870      * @constructor
43871      */
43872     Base64: function() {
43873       // private properties
43874       var tab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
43875         pad = '=', // default pad according with the RFC standard
43876         url = false, // URL encoding support @todo
43877         utf8 = true; // by default enable UTF-8 support encoding
43878
43879       // public method for encoding
43880       this.encode = function(input) {
43881         var i, j, triplet,
43882           output = '',
43883           len = input.length;
43884
43885         pad = pad || '=';
43886         input = (utf8) ? utf8Encode(input) : input;
43887
43888         for (i = 0; i < len; i += 3) {
43889           triplet = (input.charCodeAt(i) << 16) | (i + 1 < len ? input.charCodeAt(i + 1) << 8 : 0) | (i + 2 < len ? input.charCodeAt(i + 2) : 0);
43890           for (j = 0; j < 4; j += 1) {
43891             if (i * 8 + j * 6 > len * 8) {
43892               output += pad;
43893             } else {
43894               output += tab.charAt((triplet >>> 6 * (3 - j)) & 0x3F);
43895             }
43896           }
43897         }
43898         return output;
43899       };
43900
43901       // public method for decoding
43902       this.decode = function(input) {
43903         // var b64 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
43904         var i, o1, o2, o3, h1, h2, h3, h4, bits, ac,
43905           dec = '',
43906           arr = [];
43907         if (!input) {
43908           return input;
43909         }
43910
43911         i = ac = 0;
43912         input = input.replace(new RegExp('\\' + pad, 'gi'), ''); // use '='
43913         //input += '';
43914
43915         do { // unpack four hexets into three octets using index points in b64
43916           h1 = tab.indexOf(input.charAt(i += 1));
43917           h2 = tab.indexOf(input.charAt(i += 1));
43918           h3 = tab.indexOf(input.charAt(i += 1));
43919           h4 = tab.indexOf(input.charAt(i += 1));
43920
43921           bits = h1 << 18 | h2 << 12 | h3 << 6 | h4;
43922
43923           o1 = bits >> 16 & 0xff;
43924           o2 = bits >> 8 & 0xff;
43925           o3 = bits & 0xff;
43926           ac += 1;
43927
43928           if (h3 === 64) {
43929             arr[ac] = String.fromCharCode(o1);
43930           } else if (h4 === 64) {
43931             arr[ac] = String.fromCharCode(o1, o2);
43932           } else {
43933             arr[ac] = String.fromCharCode(o1, o2, o3);
43934           }
43935         } while (i < input.length);
43936
43937         dec = arr.join('');
43938         dec = (utf8) ? utf8Decode(dec) : dec;
43939
43940         return dec;
43941       };
43942
43943       // set custom pad string
43944       this.setPad = function(str) {
43945         pad = str || pad;
43946         return this;
43947       };
43948       // set custom tab string characters
43949       this.setTab = function(str) {
43950         tab = str || tab;
43951         return this;
43952       };
43953       this.setUTF8 = function(bool) {
43954         if (typeof bool === 'boolean') {
43955           utf8 = bool;
43956         }
43957         return this;
43958       };
43959     },
43960
43961     /**
43962      * CRC-32 calculation
43963      * @member Hashes
43964      * @method CRC32
43965      * @static
43966      * @param {String} str Input String
43967      * @return {String}
43968      */
43969     CRC32: function(str) {
43970       var crc = 0,
43971         x = 0,
43972         y = 0,
43973         table, i, iTop;
43974       str = utf8Encode(str);
43975
43976       table = [
43977         '00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 ',
43978         '79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 ',
43979         '84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F ',
43980         '63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD ',
43981         'A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC ',
43982         '51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 ',
43983         'B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 ',
43984         '06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 ',
43985         'E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 ',
43986         '12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 ',
43987         'D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 ',
43988         '33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 ',
43989         'CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 ',
43990         '9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E ',
43991         '7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D ',
43992         '806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 ',
43993         '60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA ',
43994         'AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 ',
43995         '5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 ',
43996         'B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 ',
43997         '05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 ',
43998         'F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA ',
43999         '11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 ',
44000         'D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F ',
44001         '30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E ',
44002         'C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D'
44003       ].join('');
44004
44005       crc = crc ^ (-1);
44006       for (i = 0, iTop = str.length; i < iTop; i += 1) {
44007         y = (crc ^ str.charCodeAt(i)) & 0xFF;
44008         x = '0x' + table.substr(y * 9, 8);
44009         crc = (crc >>> 8) ^ x;
44010       }
44011       // always return a positive number (that's what >>> 0 does)
44012       return (crc ^ (-1)) >>> 0;
44013     },
44014     /**
44015      * @member Hashes
44016      * @class MD5
44017      * @constructor
44018      * @param {Object} [config]
44019      *
44020      * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message
44021      * Digest Algorithm, as defined in RFC 1321.
44022      * Version 2.2 Copyright (C) Paul Johnston 1999 - 2009
44023      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
44024      * See <http://pajhome.org.uk/crypt/md5> for more infHashes.
44025      */
44026     MD5: function(options) {
44027       /**
44028        * Private config properties. You may need to tweak these to be compatible with
44029        * the server-side, but the defaults work in most cases.
44030        * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
44031        */
44032       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
44033         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
44034         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
44035
44036       // privileged (public) methods
44037       this.hex = function(s) {
44038         return rstr2hex(rstr(s, utf8), hexcase);
44039       };
44040       this.b64 = function(s) {
44041         return rstr2b64(rstr(s), b64pad);
44042       };
44043       this.any = function(s, e) {
44044         return rstr2any(rstr(s, utf8), e);
44045       };
44046       this.raw = function(s) {
44047         return rstr(s, utf8);
44048       };
44049       this.hex_hmac = function(k, d) {
44050         return rstr2hex(rstr_hmac(k, d), hexcase);
44051       };
44052       this.b64_hmac = function(k, d) {
44053         return rstr2b64(rstr_hmac(k, d), b64pad);
44054       };
44055       this.any_hmac = function(k, d, e) {
44056         return rstr2any(rstr_hmac(k, d), e);
44057       };
44058       /**
44059        * Perform a simple self-test to see if the VM is working
44060        * @return {String} Hexadecimal hash sample
44061        */
44062       this.vm_test = function() {
44063         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
44064       };
44065       /**
44066        * Enable/disable uppercase hexadecimal returned string
44067        * @param {Boolean}
44068        * @return {Object} this
44069        */
44070       this.setUpperCase = function(a) {
44071         if (typeof a === 'boolean') {
44072           hexcase = a;
44073         }
44074         return this;
44075       };
44076       /**
44077        * Defines a base64 pad string
44078        * @param {String} Pad
44079        * @return {Object} this
44080        */
44081       this.setPad = function(a) {
44082         b64pad = a || b64pad;
44083         return this;
44084       };
44085       /**
44086        * Defines a base64 pad string
44087        * @param {Boolean}
44088        * @return {Object} [this]
44089        */
44090       this.setUTF8 = function(a) {
44091         if (typeof a === 'boolean') {
44092           utf8 = a;
44093         }
44094         return this;
44095       };
44096
44097       // private methods
44098
44099       /**
44100        * Calculate the MD5 of a raw string
44101        */
44102
44103       function rstr(s) {
44104         s = (utf8) ? utf8Encode(s) : s;
44105         return binl2rstr(binl(rstr2binl(s), s.length * 8));
44106       }
44107
44108       /**
44109        * Calculate the HMAC-MD5, of a key and some data (raw strings)
44110        */
44111
44112       function rstr_hmac(key, data) {
44113         var bkey, ipad, opad, hash, i;
44114
44115         key = (utf8) ? utf8Encode(key) : key;
44116         data = (utf8) ? utf8Encode(data) : data;
44117         bkey = rstr2binl(key);
44118         if (bkey.length > 16) {
44119           bkey = binl(bkey, key.length * 8);
44120         }
44121
44122         ipad = Array(16), opad = Array(16);
44123         for (i = 0; i < 16; i += 1) {
44124           ipad[i] = bkey[i] ^ 0x36363636;
44125           opad[i] = bkey[i] ^ 0x5C5C5C5C;
44126         }
44127         hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
44128         return binl2rstr(binl(opad.concat(hash), 512 + 128));
44129       }
44130
44131       /**
44132        * Calculate the MD5 of an array of little-endian words, and a bit length.
44133        */
44134
44135       function binl(x, len) {
44136         var i, olda, oldb, oldc, oldd,
44137           a = 1732584193,
44138           b = -271733879,
44139           c = -1732584194,
44140           d = 271733878;
44141
44142         /* append padding */
44143         x[len >> 5] |= 0x80 << ((len) % 32);
44144         x[(((len + 64) >>> 9) << 4) + 14] = len;
44145
44146         for (i = 0; i < x.length; i += 16) {
44147           olda = a;
44148           oldb = b;
44149           oldc = c;
44150           oldd = d;
44151
44152           a = md5_ff(a, b, c, d, x[i + 0], 7, -680876936);
44153           d = md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
44154           c = md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
44155           b = md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
44156           a = md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
44157           d = md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
44158           c = md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
44159           b = md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
44160           a = md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
44161           d = md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
44162           c = md5_ff(c, d, a, b, x[i + 10], 17, -42063);
44163           b = md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
44164           a = md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
44165           d = md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
44166           c = md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
44167           b = md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);
44168
44169           a = md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
44170           d = md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
44171           c = md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
44172           b = md5_gg(b, c, d, a, x[i + 0], 20, -373897302);
44173           a = md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
44174           d = md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
44175           c = md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
44176           b = md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
44177           a = md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
44178           d = md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
44179           c = md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
44180           b = md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
44181           a = md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
44182           d = md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
44183           c = md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
44184           b = md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);
44185
44186           a = md5_hh(a, b, c, d, x[i + 5], 4, -378558);
44187           d = md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
44188           c = md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
44189           b = md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
44190           a = md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
44191           d = md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
44192           c = md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
44193           b = md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
44194           a = md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
44195           d = md5_hh(d, a, b, c, x[i + 0], 11, -358537222);
44196           c = md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
44197           b = md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
44198           a = md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
44199           d = md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
44200           c = md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
44201           b = md5_hh(b, c, d, a, x[i + 2], 23, -995338651);
44202
44203           a = md5_ii(a, b, c, d, x[i + 0], 6, -198630844);
44204           d = md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
44205           c = md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
44206           b = md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
44207           a = md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
44208           d = md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
44209           c = md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
44210           b = md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
44211           a = md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
44212           d = md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
44213           c = md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
44214           b = md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
44215           a = md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
44216           d = md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
44217           c = md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
44218           b = md5_ii(b, c, d, a, x[i + 9], 21, -343485551);
44219
44220           a = safe_add(a, olda);
44221           b = safe_add(b, oldb);
44222           c = safe_add(c, oldc);
44223           d = safe_add(d, oldd);
44224         }
44225         return Array(a, b, c, d);
44226       }
44227
44228       /**
44229        * These functions implement the four basic operations the algorithm uses.
44230        */
44231
44232       function md5_cmn(q, a, b, x, s, t) {
44233         return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s), b);
44234       }
44235
44236       function md5_ff(a, b, c, d, x, s, t) {
44237         return md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
44238       }
44239
44240       function md5_gg(a, b, c, d, x, s, t) {
44241         return md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
44242       }
44243
44244       function md5_hh(a, b, c, d, x, s, t) {
44245         return md5_cmn(b ^ c ^ d, a, b, x, s, t);
44246       }
44247
44248       function md5_ii(a, b, c, d, x, s, t) {
44249         return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
44250       }
44251     },
44252     /**
44253      * @member Hashes
44254      * @class Hashes.SHA1
44255      * @param {Object} [config]
44256      * @constructor
44257      *
44258      * A JavaScript implementation of the Secure Hash Algorithm, SHA-1, as defined in FIPS 180-1
44259      * Version 2.2 Copyright Paul Johnston 2000 - 2009.
44260      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
44261      * See http://pajhome.org.uk/crypt/md5 for details.
44262      */
44263     SHA1: function(options) {
44264       /**
44265        * Private config properties. You may need to tweak these to be compatible with
44266        * the server-side, but the defaults work in most cases.
44267        * See {@link Hashes.MD5#method-setUpperCase} and {@link Hashes.SHA1#method-setUpperCase}
44268        */
44269       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase
44270         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=', // base-64 pad character. Defaults to '=' for strict RFC compliance
44271         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true; // enable/disable utf8 encoding
44272
44273       // public methods
44274       this.hex = function(s) {
44275         return rstr2hex(rstr(s, utf8), hexcase);
44276       };
44277       this.b64 = function(s) {
44278         return rstr2b64(rstr(s, utf8), b64pad);
44279       };
44280       this.any = function(s, e) {
44281         return rstr2any(rstr(s, utf8), e);
44282       };
44283       this.raw = function(s) {
44284         return rstr(s, utf8);
44285       };
44286       this.hex_hmac = function(k, d) {
44287         return rstr2hex(rstr_hmac(k, d));
44288       };
44289       this.b64_hmac = function(k, d) {
44290         return rstr2b64(rstr_hmac(k, d), b64pad);
44291       };
44292       this.any_hmac = function(k, d, e) {
44293         return rstr2any(rstr_hmac(k, d), e);
44294       };
44295       /**
44296        * Perform a simple self-test to see if the VM is working
44297        * @return {String} Hexadecimal hash sample
44298        * @public
44299        */
44300       this.vm_test = function() {
44301         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
44302       };
44303       /**
44304        * @description Enable/disable uppercase hexadecimal returned string
44305        * @param {boolean}
44306        * @return {Object} this
44307        * @public
44308        */
44309       this.setUpperCase = function(a) {
44310         if (typeof a === 'boolean') {
44311           hexcase = a;
44312         }
44313         return this;
44314       };
44315       /**
44316        * @description Defines a base64 pad string
44317        * @param {string} Pad
44318        * @return {Object} this
44319        * @public
44320        */
44321       this.setPad = function(a) {
44322         b64pad = a || b64pad;
44323         return this;
44324       };
44325       /**
44326        * @description Defines a base64 pad string
44327        * @param {boolean}
44328        * @return {Object} this
44329        * @public
44330        */
44331       this.setUTF8 = function(a) {
44332         if (typeof a === 'boolean') {
44333           utf8 = a;
44334         }
44335         return this;
44336       };
44337
44338       // private methods
44339
44340       /**
44341        * Calculate the SHA-512 of a raw string
44342        */
44343
44344       function rstr(s) {
44345         s = (utf8) ? utf8Encode(s) : s;
44346         return binb2rstr(binb(rstr2binb(s), s.length * 8));
44347       }
44348
44349       /**
44350        * Calculate the HMAC-SHA1 of a key and some data (raw strings)
44351        */
44352
44353       function rstr_hmac(key, data) {
44354         var bkey, ipad, opad, i, hash;
44355         key = (utf8) ? utf8Encode(key) : key;
44356         data = (utf8) ? utf8Encode(data) : data;
44357         bkey = rstr2binb(key);
44358
44359         if (bkey.length > 16) {
44360           bkey = binb(bkey, key.length * 8);
44361         }
44362         ipad = Array(16), opad = Array(16);
44363         for (i = 0; i < 16; i += 1) {
44364           ipad[i] = bkey[i] ^ 0x36363636;
44365           opad[i] = bkey[i] ^ 0x5C5C5C5C;
44366         }
44367         hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
44368         return binb2rstr(binb(opad.concat(hash), 512 + 160));
44369       }
44370
44371       /**
44372        * Calculate the SHA-1 of an array of big-endian words, and a bit length
44373        */
44374
44375       function binb(x, len) {
44376         var i, j, t, olda, oldb, oldc, oldd, olde,
44377           w = Array(80),
44378           a = 1732584193,
44379           b = -271733879,
44380           c = -1732584194,
44381           d = 271733878,
44382           e = -1009589776;
44383
44384         /* append padding */
44385         x[len >> 5] |= 0x80 << (24 - len % 32);
44386         x[((len + 64 >> 9) << 4) + 15] = len;
44387
44388         for (i = 0; i < x.length; i += 16) {
44389           olda = a,
44390           oldb = b;
44391           oldc = c;
44392           oldd = d;
44393           olde = e;
44394
44395           for (j = 0; j < 80; j += 1) {
44396             if (j < 16) {
44397               w[j] = x[i + j];
44398             } else {
44399               w[j] = bit_rol(w[j - 3] ^ w[j - 8] ^ w[j - 14] ^ w[j - 16], 1);
44400             }
44401             t = safe_add(safe_add(bit_rol(a, 5), sha1_ft(j, b, c, d)),
44402               safe_add(safe_add(e, w[j]), sha1_kt(j)));
44403             e = d;
44404             d = c;
44405             c = bit_rol(b, 30);
44406             b = a;
44407             a = t;
44408           }
44409
44410           a = safe_add(a, olda);
44411           b = safe_add(b, oldb);
44412           c = safe_add(c, oldc);
44413           d = safe_add(d, oldd);
44414           e = safe_add(e, olde);
44415         }
44416         return Array(a, b, c, d, e);
44417       }
44418
44419       /**
44420        * Perform the appropriate triplet combination function for the current
44421        * iteration
44422        */
44423
44424       function sha1_ft(t, b, c, d) {
44425         if (t < 20) {
44426           return (b & c) | ((~b) & d);
44427         }
44428         if (t < 40) {
44429           return b ^ c ^ d;
44430         }
44431         if (t < 60) {
44432           return (b & c) | (b & d) | (c & d);
44433         }
44434         return b ^ c ^ d;
44435       }
44436
44437       /**
44438        * Determine the appropriate additive constant for the current iteration
44439        */
44440
44441       function sha1_kt(t) {
44442         return (t < 20) ? 1518500249 : (t < 40) ? 1859775393 :
44443           (t < 60) ? -1894007588 : -899497514;
44444       }
44445     },
44446     /**
44447      * @class Hashes.SHA256
44448      * @param {config}
44449      *
44450      * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined in FIPS 180-2
44451      * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009.
44452      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
44453      * See http://pajhome.org.uk/crypt/md5 for details.
44454      * Also http://anmar.eu.org/projects/jssha2/
44455      */
44456     SHA256: function(options) {
44457       /**
44458        * Private properties configuration variables. You may need to tweak these to be compatible with
44459        * the server-side, but the defaults work in most cases.
44460        * @see this.setUpperCase() method
44461        * @see this.setPad() method
44462        */
44463       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false, // hexadecimal output case format. false - lowercase; true - uppercase  */
44464         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',
44465         /* base-64 pad character. Default '=' for strict RFC compliance   */
44466         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
44467         /* enable/disable utf8 encoding */
44468         sha256_K;
44469
44470       /* privileged (public) methods */
44471       this.hex = function(s) {
44472         return rstr2hex(rstr(s, utf8));
44473       };
44474       this.b64 = function(s) {
44475         return rstr2b64(rstr(s, utf8), b64pad);
44476       };
44477       this.any = function(s, e) {
44478         return rstr2any(rstr(s, utf8), e);
44479       };
44480       this.raw = function(s) {
44481         return rstr(s, utf8);
44482       };
44483       this.hex_hmac = function(k, d) {
44484         return rstr2hex(rstr_hmac(k, d));
44485       };
44486       this.b64_hmac = function(k, d) {
44487         return rstr2b64(rstr_hmac(k, d), b64pad);
44488       };
44489       this.any_hmac = function(k, d, e) {
44490         return rstr2any(rstr_hmac(k, d), e);
44491       };
44492       /**
44493        * Perform a simple self-test to see if the VM is working
44494        * @return {String} Hexadecimal hash sample
44495        * @public
44496        */
44497       this.vm_test = function() {
44498         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
44499       };
44500       /**
44501        * Enable/disable uppercase hexadecimal returned string
44502        * @param {boolean}
44503        * @return {Object} this
44504        * @public
44505        */
44506       this.setUpperCase = function(a) {
44507         if (typeof a === 'boolean') {
44508           hexcase = a;
44509         }
44510         return this;
44511       };
44512       /**
44513        * @description Defines a base64 pad string
44514        * @param {string} Pad
44515        * @return {Object} this
44516        * @public
44517        */
44518       this.setPad = function(a) {
44519         b64pad = a || b64pad;
44520         return this;
44521       };
44522       /**
44523        * Defines a base64 pad string
44524        * @param {boolean}
44525        * @return {Object} this
44526        * @public
44527        */
44528       this.setUTF8 = function(a) {
44529         if (typeof a === 'boolean') {
44530           utf8 = a;
44531         }
44532         return this;
44533       };
44534
44535       // private methods
44536
44537       /**
44538        * Calculate the SHA-512 of a raw string
44539        */
44540
44541       function rstr(s, utf8) {
44542         s = (utf8) ? utf8Encode(s) : s;
44543         return binb2rstr(binb(rstr2binb(s), s.length * 8));
44544       }
44545
44546       /**
44547        * Calculate the HMAC-sha256 of a key and some data (raw strings)
44548        */
44549
44550       function rstr_hmac(key, data) {
44551         key = (utf8) ? utf8Encode(key) : key;
44552         data = (utf8) ? utf8Encode(data) : data;
44553         var hash, i = 0,
44554           bkey = rstr2binb(key),
44555           ipad = Array(16),
44556           opad = Array(16);
44557
44558         if (bkey.length > 16) {
44559           bkey = binb(bkey, key.length * 8);
44560         }
44561
44562         for (; i < 16; i += 1) {
44563           ipad[i] = bkey[i] ^ 0x36363636;
44564           opad[i] = bkey[i] ^ 0x5C5C5C5C;
44565         }
44566
44567         hash = binb(ipad.concat(rstr2binb(data)), 512 + data.length * 8);
44568         return binb2rstr(binb(opad.concat(hash), 512 + 256));
44569       }
44570
44571       /*
44572        * Main sha256 function, with its support functions
44573        */
44574
44575       function sha256_S(X, n) {
44576         return (X >>> n) | (X << (32 - n));
44577       }
44578
44579       function sha256_R(X, n) {
44580         return (X >>> n);
44581       }
44582
44583       function sha256_Ch(x, y, z) {
44584         return ((x & y) ^ ((~x) & z));
44585       }
44586
44587       function sha256_Maj(x, y, z) {
44588         return ((x & y) ^ (x & z) ^ (y & z));
44589       }
44590
44591       function sha256_Sigma0256(x) {
44592         return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22));
44593       }
44594
44595       function sha256_Sigma1256(x) {
44596         return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25));
44597       }
44598
44599       function sha256_Gamma0256(x) {
44600         return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3));
44601       }
44602
44603       function sha256_Gamma1256(x) {
44604         return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10));
44605       }
44606
44607       function sha256_Sigma0512(x) {
44608         return (sha256_S(x, 28) ^ sha256_S(x, 34) ^ sha256_S(x, 39));
44609       }
44610
44611       function sha256_Sigma1512(x) {
44612         return (sha256_S(x, 14) ^ sha256_S(x, 18) ^ sha256_S(x, 41));
44613       }
44614
44615       function sha256_Gamma0512(x) {
44616         return (sha256_S(x, 1) ^ sha256_S(x, 8) ^ sha256_R(x, 7));
44617       }
44618
44619       function sha256_Gamma1512(x) {
44620         return (sha256_S(x, 19) ^ sha256_S(x, 61) ^ sha256_R(x, 6));
44621       }
44622
44623       sha256_K = [
44624         1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987,
44625         1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522,
44626         264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585,
44627         113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291,
44628         1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885, -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344,
44629         430227734, 506948616, 659060556, 883997877, 958139571, 1322822218,
44630         1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872, -1866530822, -1538233109, -1090935817, -965641998
44631       ];
44632
44633       function binb(m, l) {
44634         var HASH = [1779033703, -1150833019, 1013904242, -1521486534,
44635           1359893119, -1694144372, 528734635, 1541459225
44636         ];
44637         var W = new Array(64);
44638         var a, b, c, d, e, f, g, h;
44639         var i, j, T1, T2;
44640
44641         /* append padding */
44642         m[l >> 5] |= 0x80 << (24 - l % 32);
44643         m[((l + 64 >> 9) << 4) + 15] = l;
44644
44645         for (i = 0; i < m.length; i += 16) {
44646           a = HASH[0];
44647           b = HASH[1];
44648           c = HASH[2];
44649           d = HASH[3];
44650           e = HASH[4];
44651           f = HASH[5];
44652           g = HASH[6];
44653           h = HASH[7];
44654
44655           for (j = 0; j < 64; j += 1) {
44656             if (j < 16) {
44657               W[j] = m[j + i];
44658             } else {
44659               W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]),
44660                 sha256_Gamma0256(W[j - 15])), W[j - 16]);
44661             }
44662
44663             T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)),
44664               sha256_K[j]), W[j]);
44665             T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c));
44666             h = g;
44667             g = f;
44668             f = e;
44669             e = safe_add(d, T1);
44670             d = c;
44671             c = b;
44672             b = a;
44673             a = safe_add(T1, T2);
44674           }
44675
44676           HASH[0] = safe_add(a, HASH[0]);
44677           HASH[1] = safe_add(b, HASH[1]);
44678           HASH[2] = safe_add(c, HASH[2]);
44679           HASH[3] = safe_add(d, HASH[3]);
44680           HASH[4] = safe_add(e, HASH[4]);
44681           HASH[5] = safe_add(f, HASH[5]);
44682           HASH[6] = safe_add(g, HASH[6]);
44683           HASH[7] = safe_add(h, HASH[7]);
44684         }
44685         return HASH;
44686       }
44687
44688     },
44689
44690     /**
44691      * @class Hashes.SHA512
44692      * @param {config}
44693      *
44694      * A JavaScript implementation of the Secure Hash Algorithm, SHA-512, as defined in FIPS 180-2
44695      * Version 2.2 Copyright Anonymous Contributor, Paul Johnston 2000 - 2009.
44696      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
44697      * See http://pajhome.org.uk/crypt/md5 for details.
44698      */
44699     SHA512: function(options) {
44700       /**
44701        * Private properties configuration variables. You may need to tweak these to be compatible with
44702        * the server-side, but the defaults work in most cases.
44703        * @see this.setUpperCase() method
44704        * @see this.setPad() method
44705        */
44706       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false,
44707         /* hexadecimal output case format. false - lowercase; true - uppercase  */
44708         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',
44709         /* base-64 pad character. Default '=' for strict RFC compliance   */
44710         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
44711         /* enable/disable utf8 encoding */
44712         sha512_k;
44713
44714       /* privileged (public) methods */
44715       this.hex = function(s) {
44716         return rstr2hex(rstr(s));
44717       };
44718       this.b64 = function(s) {
44719         return rstr2b64(rstr(s), b64pad);
44720       };
44721       this.any = function(s, e) {
44722         return rstr2any(rstr(s), e);
44723       };
44724       this.raw = function(s) {
44725         return rstr(s, utf8);
44726       };
44727       this.hex_hmac = function(k, d) {
44728         return rstr2hex(rstr_hmac(k, d));
44729       };
44730       this.b64_hmac = function(k, d) {
44731         return rstr2b64(rstr_hmac(k, d), b64pad);
44732       };
44733       this.any_hmac = function(k, d, e) {
44734         return rstr2any(rstr_hmac(k, d), e);
44735       };
44736       /**
44737        * Perform a simple self-test to see if the VM is working
44738        * @return {String} Hexadecimal hash sample
44739        * @public
44740        */
44741       this.vm_test = function() {
44742         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
44743       };
44744       /**
44745        * @description Enable/disable uppercase hexadecimal returned string
44746        * @param {boolean}
44747        * @return {Object} this
44748        * @public
44749        */
44750       this.setUpperCase = function(a) {
44751         if (typeof a === 'boolean') {
44752           hexcase = a;
44753         }
44754         return this;
44755       };
44756       /**
44757        * @description Defines a base64 pad string
44758        * @param {string} Pad
44759        * @return {Object} this
44760        * @public
44761        */
44762       this.setPad = function(a) {
44763         b64pad = a || b64pad;
44764         return this;
44765       };
44766       /**
44767        * @description Defines a base64 pad string
44768        * @param {boolean}
44769        * @return {Object} this
44770        * @public
44771        */
44772       this.setUTF8 = function(a) {
44773         if (typeof a === 'boolean') {
44774           utf8 = a;
44775         }
44776         return this;
44777       };
44778
44779       /* private methods */
44780
44781       /**
44782        * Calculate the SHA-512 of a raw string
44783        */
44784
44785       function rstr(s) {
44786         s = (utf8) ? utf8Encode(s) : s;
44787         return binb2rstr(binb(rstr2binb(s), s.length * 8));
44788       }
44789       /*
44790        * Calculate the HMAC-SHA-512 of a key and some data (raw strings)
44791        */
44792
44793       function rstr_hmac(key, data) {
44794         key = (utf8) ? utf8Encode(key) : key;
44795         data = (utf8) ? utf8Encode(data) : data;
44796
44797         var hash, i = 0,
44798           bkey = rstr2binb(key),
44799           ipad = Array(32),
44800           opad = Array(32);
44801
44802         if (bkey.length > 32) {
44803           bkey = binb(bkey, key.length * 8);
44804         }
44805
44806         for (; i < 32; i += 1) {
44807           ipad[i] = bkey[i] ^ 0x36363636;
44808           opad[i] = bkey[i] ^ 0x5C5C5C5C;
44809         }
44810
44811         hash = binb(ipad.concat(rstr2binb(data)), 1024 + data.length * 8);
44812         return binb2rstr(binb(opad.concat(hash), 1024 + 512));
44813       }
44814
44815       /**
44816        * Calculate the SHA-512 of an array of big-endian dwords, and a bit length
44817        */
44818
44819       function binb(x, len) {
44820         var j, i, l,
44821           W = new Array(80),
44822           hash = new Array(16),
44823           //Initial hash values
44824           H = [
44825             new int64(0x6a09e667, -205731576),
44826             new int64(-1150833019, -2067093701),
44827             new int64(0x3c6ef372, -23791573),
44828             new int64(-1521486534, 0x5f1d36f1),
44829             new int64(0x510e527f, -1377402159),
44830             new int64(-1694144372, 0x2b3e6c1f),
44831             new int64(0x1f83d9ab, -79577749),
44832             new int64(0x5be0cd19, 0x137e2179)
44833           ],
44834           T1 = new int64(0, 0),
44835           T2 = new int64(0, 0),
44836           a = new int64(0, 0),
44837           b = new int64(0, 0),
44838           c = new int64(0, 0),
44839           d = new int64(0, 0),
44840           e = new int64(0, 0),
44841           f = new int64(0, 0),
44842           g = new int64(0, 0),
44843           h = new int64(0, 0),
44844           //Temporary variables not specified by the document
44845           s0 = new int64(0, 0),
44846           s1 = new int64(0, 0),
44847           Ch = new int64(0, 0),
44848           Maj = new int64(0, 0),
44849           r1 = new int64(0, 0),
44850           r2 = new int64(0, 0),
44851           r3 = new int64(0, 0);
44852
44853         if (sha512_k === undefined) {
44854           //SHA512 constants
44855           sha512_k = [
44856             new int64(0x428a2f98, -685199838), new int64(0x71374491, 0x23ef65cd),
44857             new int64(-1245643825, -330482897), new int64(-373957723, -2121671748),
44858             new int64(0x3956c25b, -213338824), new int64(0x59f111f1, -1241133031),
44859             new int64(-1841331548, -1357295717), new int64(-1424204075, -630357736),
44860             new int64(-670586216, -1560083902), new int64(0x12835b01, 0x45706fbe),
44861             new int64(0x243185be, 0x4ee4b28c), new int64(0x550c7dc3, -704662302),
44862             new int64(0x72be5d74, -226784913), new int64(-2132889090, 0x3b1696b1),
44863             new int64(-1680079193, 0x25c71235), new int64(-1046744716, -815192428),
44864             new int64(-459576895, -1628353838), new int64(-272742522, 0x384f25e3),
44865             new int64(0xfc19dc6, -1953704523), new int64(0x240ca1cc, 0x77ac9c65),
44866             new int64(0x2de92c6f, 0x592b0275), new int64(0x4a7484aa, 0x6ea6e483),
44867             new int64(0x5cb0a9dc, -1119749164), new int64(0x76f988da, -2096016459),
44868             new int64(-1740746414, -295247957), new int64(-1473132947, 0x2db43210),
44869             new int64(-1341970488, -1728372417), new int64(-1084653625, -1091629340),
44870             new int64(-958395405, 0x3da88fc2), new int64(-710438585, -1828018395),
44871             new int64(0x6ca6351, -536640913), new int64(0x14292967, 0xa0e6e70),
44872             new int64(0x27b70a85, 0x46d22ffc), new int64(0x2e1b2138, 0x5c26c926),
44873             new int64(0x4d2c6dfc, 0x5ac42aed), new int64(0x53380d13, -1651133473),
44874             new int64(0x650a7354, -1951439906), new int64(0x766a0abb, 0x3c77b2a8),
44875             new int64(-2117940946, 0x47edaee6), new int64(-1838011259, 0x1482353b),
44876             new int64(-1564481375, 0x4cf10364), new int64(-1474664885, -1136513023),
44877             new int64(-1035236496, -789014639), new int64(-949202525, 0x654be30),
44878             new int64(-778901479, -688958952), new int64(-694614492, 0x5565a910),
44879             new int64(-200395387, 0x5771202a), new int64(0x106aa070, 0x32bbd1b8),
44880             new int64(0x19a4c116, -1194143544), new int64(0x1e376c08, 0x5141ab53),
44881             new int64(0x2748774c, -544281703), new int64(0x34b0bcb5, -509917016),
44882             new int64(0x391c0cb3, -976659869), new int64(0x4ed8aa4a, -482243893),
44883             new int64(0x5b9cca4f, 0x7763e373), new int64(0x682e6ff3, -692930397),
44884             new int64(0x748f82ee, 0x5defb2fc), new int64(0x78a5636f, 0x43172f60),
44885             new int64(-2067236844, -1578062990), new int64(-1933114872, 0x1a6439ec),
44886             new int64(-1866530822, 0x23631e28), new int64(-1538233109, -561857047),
44887             new int64(-1090935817, -1295615723), new int64(-965641998, -479046869),
44888             new int64(-903397682, -366583396), new int64(-779700025, 0x21c0c207),
44889             new int64(-354779690, -840897762), new int64(-176337025, -294727304),
44890             new int64(0x6f067aa, 0x72176fba), new int64(0xa637dc5, -1563912026),
44891             new int64(0x113f9804, -1090974290), new int64(0x1b710b35, 0x131c471b),
44892             new int64(0x28db77f5, 0x23047d84), new int64(0x32caab7b, 0x40c72493),
44893             new int64(0x3c9ebe0a, 0x15c9bebc), new int64(0x431d67c4, -1676669620),
44894             new int64(0x4cc5d4be, -885112138), new int64(0x597f299c, -60457430),
44895             new int64(0x5fcb6fab, 0x3ad6faec), new int64(0x6c44198c, 0x4a475817)
44896           ];
44897         }
44898
44899         for (i = 0; i < 80; i += 1) {
44900           W[i] = new int64(0, 0);
44901         }
44902
44903         // append padding to the source string. The format is described in the FIPS.
44904         x[len >> 5] |= 0x80 << (24 - (len & 0x1f));
44905         x[((len + 128 >> 10) << 5) + 31] = len;
44906         l = x.length;
44907         for (i = 0; i < l; i += 32) { //32 dwords is the block size
44908           int64copy(a, H[0]);
44909           int64copy(b, H[1]);
44910           int64copy(c, H[2]);
44911           int64copy(d, H[3]);
44912           int64copy(e, H[4]);
44913           int64copy(f, H[5]);
44914           int64copy(g, H[6]);
44915           int64copy(h, H[7]);
44916
44917           for (j = 0; j < 16; j += 1) {
44918             W[j].h = x[i + 2 * j];
44919             W[j].l = x[i + 2 * j + 1];
44920           }
44921
44922           for (j = 16; j < 80; j += 1) {
44923             //sigma1
44924             int64rrot(r1, W[j - 2], 19);
44925             int64revrrot(r2, W[j - 2], 29);
44926             int64shr(r3, W[j - 2], 6);
44927             s1.l = r1.l ^ r2.l ^ r3.l;
44928             s1.h = r1.h ^ r2.h ^ r3.h;
44929             //sigma0
44930             int64rrot(r1, W[j - 15], 1);
44931             int64rrot(r2, W[j - 15], 8);
44932             int64shr(r3, W[j - 15], 7);
44933             s0.l = r1.l ^ r2.l ^ r3.l;
44934             s0.h = r1.h ^ r2.h ^ r3.h;
44935
44936             int64add4(W[j], s1, W[j - 7], s0, W[j - 16]);
44937           }
44938
44939           for (j = 0; j < 80; j += 1) {
44940             //Ch
44941             Ch.l = (e.l & f.l) ^ (~e.l & g.l);
44942             Ch.h = (e.h & f.h) ^ (~e.h & g.h);
44943
44944             //Sigma1
44945             int64rrot(r1, e, 14);
44946             int64rrot(r2, e, 18);
44947             int64revrrot(r3, e, 9);
44948             s1.l = r1.l ^ r2.l ^ r3.l;
44949             s1.h = r1.h ^ r2.h ^ r3.h;
44950
44951             //Sigma0
44952             int64rrot(r1, a, 28);
44953             int64revrrot(r2, a, 2);
44954             int64revrrot(r3, a, 7);
44955             s0.l = r1.l ^ r2.l ^ r3.l;
44956             s0.h = r1.h ^ r2.h ^ r3.h;
44957
44958             //Maj
44959             Maj.l = (a.l & b.l) ^ (a.l & c.l) ^ (b.l & c.l);
44960             Maj.h = (a.h & b.h) ^ (a.h & c.h) ^ (b.h & c.h);
44961
44962             int64add5(T1, h, s1, Ch, sha512_k[j], W[j]);
44963             int64add(T2, s0, Maj);
44964
44965             int64copy(h, g);
44966             int64copy(g, f);
44967             int64copy(f, e);
44968             int64add(e, d, T1);
44969             int64copy(d, c);
44970             int64copy(c, b);
44971             int64copy(b, a);
44972             int64add(a, T1, T2);
44973           }
44974           int64add(H[0], H[0], a);
44975           int64add(H[1], H[1], b);
44976           int64add(H[2], H[2], c);
44977           int64add(H[3], H[3], d);
44978           int64add(H[4], H[4], e);
44979           int64add(H[5], H[5], f);
44980           int64add(H[6], H[6], g);
44981           int64add(H[7], H[7], h);
44982         }
44983
44984         //represent the hash as an array of 32-bit dwords
44985         for (i = 0; i < 8; i += 1) {
44986           hash[2 * i] = H[i].h;
44987           hash[2 * i + 1] = H[i].l;
44988         }
44989         return hash;
44990       }
44991
44992       //A constructor for 64-bit numbers
44993
44994       function int64(h, l) {
44995         this.h = h;
44996         this.l = l;
44997         //this.toString = int64toString;
44998       }
44999
45000       //Copies src into dst, assuming both are 64-bit numbers
45001
45002       function int64copy(dst, src) {
45003         dst.h = src.h;
45004         dst.l = src.l;
45005       }
45006
45007       //Right-rotates a 64-bit number by shift
45008       //Won't handle cases of shift>=32
45009       //The function revrrot() is for that
45010
45011       function int64rrot(dst, x, shift) {
45012         dst.l = (x.l >>> shift) | (x.h << (32 - shift));
45013         dst.h = (x.h >>> shift) | (x.l << (32 - shift));
45014       }
45015
45016       //Reverses the dwords of the source and then rotates right by shift.
45017       //This is equivalent to rotation by 32+shift
45018
45019       function int64revrrot(dst, x, shift) {
45020         dst.l = (x.h >>> shift) | (x.l << (32 - shift));
45021         dst.h = (x.l >>> shift) | (x.h << (32 - shift));
45022       }
45023
45024       //Bitwise-shifts right a 64-bit number by shift
45025       //Won't handle shift>=32, but it's never needed in SHA512
45026
45027       function int64shr(dst, x, shift) {
45028         dst.l = (x.l >>> shift) | (x.h << (32 - shift));
45029         dst.h = (x.h >>> shift);
45030       }
45031
45032       //Adds two 64-bit numbers
45033       //Like the original implementation, does not rely on 32-bit operations
45034
45035       function int64add(dst, x, y) {
45036         var w0 = (x.l & 0xffff) + (y.l & 0xffff);
45037         var w1 = (x.l >>> 16) + (y.l >>> 16) + (w0 >>> 16);
45038         var w2 = (x.h & 0xffff) + (y.h & 0xffff) + (w1 >>> 16);
45039         var w3 = (x.h >>> 16) + (y.h >>> 16) + (w2 >>> 16);
45040         dst.l = (w0 & 0xffff) | (w1 << 16);
45041         dst.h = (w2 & 0xffff) | (w3 << 16);
45042       }
45043
45044       //Same, except with 4 addends. Works faster than adding them one by one.
45045
45046       function int64add4(dst, a, b, c, d) {
45047         var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff);
45048         var w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (w0 >>> 16);
45049         var w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (w1 >>> 16);
45050         var w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (w2 >>> 16);
45051         dst.l = (w0 & 0xffff) | (w1 << 16);
45052         dst.h = (w2 & 0xffff) | (w3 << 16);
45053       }
45054
45055       //Same, except with 5 addends
45056
45057       function int64add5(dst, a, b, c, d, e) {
45058         var w0 = (a.l & 0xffff) + (b.l & 0xffff) + (c.l & 0xffff) + (d.l & 0xffff) + (e.l & 0xffff),
45059           w1 = (a.l >>> 16) + (b.l >>> 16) + (c.l >>> 16) + (d.l >>> 16) + (e.l >>> 16) + (w0 >>> 16),
45060           w2 = (a.h & 0xffff) + (b.h & 0xffff) + (c.h & 0xffff) + (d.h & 0xffff) + (e.h & 0xffff) + (w1 >>> 16),
45061           w3 = (a.h >>> 16) + (b.h >>> 16) + (c.h >>> 16) + (d.h >>> 16) + (e.h >>> 16) + (w2 >>> 16);
45062         dst.l = (w0 & 0xffff) | (w1 << 16);
45063         dst.h = (w2 & 0xffff) | (w3 << 16);
45064       }
45065     },
45066     /**
45067      * @class Hashes.RMD160
45068      * @constructor
45069      * @param {Object} [config]
45070      *
45071      * A JavaScript implementation of the RIPEMD-160 Algorithm
45072      * Version 2.2 Copyright Jeremy Lin, Paul Johnston 2000 - 2009.
45073      * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet
45074      * See http://pajhome.org.uk/crypt/md5 for details.
45075      * Also http://www.ocf.berkeley.edu/~jjlin/jsotp/
45076      */
45077     RMD160: function(options) {
45078       /**
45079        * Private properties configuration variables. You may need to tweak these to be compatible with
45080        * the server-side, but the defaults work in most cases.
45081        * @see this.setUpperCase() method
45082        * @see this.setPad() method
45083        */
45084       var hexcase = (options && typeof options.uppercase === 'boolean') ? options.uppercase : false,
45085         /* hexadecimal output case format. false - lowercase; true - uppercase  */
45086         b64pad = (options && typeof options.pad === 'string') ? options.pda : '=',
45087         /* base-64 pad character. Default '=' for strict RFC compliance   */
45088         utf8 = (options && typeof options.utf8 === 'boolean') ? options.utf8 : true,
45089         /* enable/disable utf8 encoding */
45090         rmd160_r1 = [
45091           0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
45092           7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8,
45093           3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12,
45094           1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2,
45095           4, 0, 5, 9, 7, 12, 2, 10, 14, 1, 3, 8, 11, 6, 15, 13
45096         ],
45097         rmd160_r2 = [
45098           5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12,
45099           6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2,
45100           15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13,
45101           8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14,
45102           12, 15, 10, 4, 1, 5, 8, 7, 6, 2, 13, 14, 0, 3, 9, 11
45103         ],
45104         rmd160_s1 = [
45105           11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8,
45106           7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12,
45107           11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5,
45108           11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12,
45109           9, 15, 5, 11, 6, 8, 13, 12, 5, 12, 13, 14, 11, 8, 5, 6
45110         ],
45111         rmd160_s2 = [
45112           8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6,
45113           9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11,
45114           9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5,
45115           15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8,
45116           8, 5, 12, 9, 12, 5, 14, 6, 8, 13, 6, 5, 15, 13, 11, 11
45117         ];
45118
45119       /* privileged (public) methods */
45120       this.hex = function(s) {
45121         return rstr2hex(rstr(s, utf8));
45122       };
45123       this.b64 = function(s) {
45124         return rstr2b64(rstr(s, utf8), b64pad);
45125       };
45126       this.any = function(s, e) {
45127         return rstr2any(rstr(s, utf8), e);
45128       };
45129       this.raw = function(s) {
45130         return rstr(s, utf8);
45131       };
45132       this.hex_hmac = function(k, d) {
45133         return rstr2hex(rstr_hmac(k, d));
45134       };
45135       this.b64_hmac = function(k, d) {
45136         return rstr2b64(rstr_hmac(k, d), b64pad);
45137       };
45138       this.any_hmac = function(k, d, e) {
45139         return rstr2any(rstr_hmac(k, d), e);
45140       };
45141       /**
45142        * Perform a simple self-test to see if the VM is working
45143        * @return {String} Hexadecimal hash sample
45144        * @public
45145        */
45146       this.vm_test = function() {
45147         return hex('abc').toLowerCase() === '900150983cd24fb0d6963f7d28e17f72';
45148       };
45149       /**
45150        * @description Enable/disable uppercase hexadecimal returned string
45151        * @param {boolean}
45152        * @return {Object} this
45153        * @public
45154        */
45155       this.setUpperCase = function(a) {
45156         if (typeof a === 'boolean') {
45157           hexcase = a;
45158         }
45159         return this;
45160       };
45161       /**
45162        * @description Defines a base64 pad string
45163        * @param {string} Pad
45164        * @return {Object} this
45165        * @public
45166        */
45167       this.setPad = function(a) {
45168         if (typeof a !== 'undefined') {
45169           b64pad = a;
45170         }
45171         return this;
45172       };
45173       /**
45174        * @description Defines a base64 pad string
45175        * @param {boolean}
45176        * @return {Object} this
45177        * @public
45178        */
45179       this.setUTF8 = function(a) {
45180         if (typeof a === 'boolean') {
45181           utf8 = a;
45182         }
45183         return this;
45184       };
45185
45186       /* private methods */
45187
45188       /**
45189        * Calculate the rmd160 of a raw string
45190        */
45191
45192       function rstr(s) {
45193         s = (utf8) ? utf8Encode(s) : s;
45194         return binl2rstr(binl(rstr2binl(s), s.length * 8));
45195       }
45196
45197       /**
45198        * Calculate the HMAC-rmd160 of a key and some data (raw strings)
45199        */
45200
45201       function rstr_hmac(key, data) {
45202         key = (utf8) ? utf8Encode(key) : key;
45203         data = (utf8) ? utf8Encode(data) : data;
45204         var i, hash,
45205           bkey = rstr2binl(key),
45206           ipad = Array(16),
45207           opad = Array(16);
45208
45209         if (bkey.length > 16) {
45210           bkey = binl(bkey, key.length * 8);
45211         }
45212
45213         for (i = 0; i < 16; i += 1) {
45214           ipad[i] = bkey[i] ^ 0x36363636;
45215           opad[i] = bkey[i] ^ 0x5C5C5C5C;
45216         }
45217         hash = binl(ipad.concat(rstr2binl(data)), 512 + data.length * 8);
45218         return binl2rstr(binl(opad.concat(hash), 512 + 160));
45219       }
45220
45221       /**
45222        * Convert an array of little-endian words to a string
45223        */
45224
45225       function binl2rstr(input) {
45226         var i, output = '',
45227           l = input.length * 32;
45228         for (i = 0; i < l; i += 8) {
45229           output += String.fromCharCode((input[i >> 5] >>> (i % 32)) & 0xFF);
45230         }
45231         return output;
45232       }
45233
45234       /**
45235        * Calculate the RIPE-MD160 of an array of little-endian words, and a bit length.
45236        */
45237
45238       function binl(x, len) {
45239         var T, j, i, l,
45240           h0 = 0x67452301,
45241           h1 = 0xefcdab89,
45242           h2 = 0x98badcfe,
45243           h3 = 0x10325476,
45244           h4 = 0xc3d2e1f0,
45245           A1, B1, C1, D1, E1,
45246           A2, B2, C2, D2, E2;
45247
45248         /* append padding */
45249         x[len >> 5] |= 0x80 << (len % 32);
45250         x[(((len + 64) >>> 9) << 4) + 14] = len;
45251         l = x.length;
45252
45253         for (i = 0; i < l; i += 16) {
45254           A1 = A2 = h0;
45255           B1 = B2 = h1;
45256           C1 = C2 = h2;
45257           D1 = D2 = h3;
45258           E1 = E2 = h4;
45259           for (j = 0; j <= 79; j += 1) {
45260             T = safe_add(A1, rmd160_f(j, B1, C1, D1));
45261             T = safe_add(T, x[i + rmd160_r1[j]]);
45262             T = safe_add(T, rmd160_K1(j));
45263             T = safe_add(bit_rol(T, rmd160_s1[j]), E1);
45264             A1 = E1;
45265             E1 = D1;
45266             D1 = bit_rol(C1, 10);
45267             C1 = B1;
45268             B1 = T;
45269             T = safe_add(A2, rmd160_f(79 - j, B2, C2, D2));
45270             T = safe_add(T, x[i + rmd160_r2[j]]);
45271             T = safe_add(T, rmd160_K2(j));
45272             T = safe_add(bit_rol(T, rmd160_s2[j]), E2);
45273             A2 = E2;
45274             E2 = D2;
45275             D2 = bit_rol(C2, 10);
45276             C2 = B2;
45277             B2 = T;
45278           }
45279
45280           T = safe_add(h1, safe_add(C1, D2));
45281           h1 = safe_add(h2, safe_add(D1, E2));
45282           h2 = safe_add(h3, safe_add(E1, A2));
45283           h3 = safe_add(h4, safe_add(A1, B2));
45284           h4 = safe_add(h0, safe_add(B1, C2));
45285           h0 = T;
45286         }
45287         return [h0, h1, h2, h3, h4];
45288       }
45289
45290       // specific algorithm methods
45291
45292       function rmd160_f(j, x, y, z) {
45293         return (0 <= j && j <= 15) ? (x ^ y ^ z) :
45294           (16 <= j && j <= 31) ? (x & y) | (~x & z) :
45295           (32 <= j && j <= 47) ? (x | ~y) ^ z :
45296           (48 <= j && j <= 63) ? (x & z) | (y & ~z) :
45297           (64 <= j && j <= 79) ? x ^ (y | ~z) :
45298           'rmd160_f: j out of range';
45299       }
45300
45301       function rmd160_K1(j) {
45302         return (0 <= j && j <= 15) ? 0x00000000 :
45303           (16 <= j && j <= 31) ? 0x5a827999 :
45304           (32 <= j && j <= 47) ? 0x6ed9eba1 :
45305           (48 <= j && j <= 63) ? 0x8f1bbcdc :
45306           (64 <= j && j <= 79) ? 0xa953fd4e :
45307           'rmd160_K1: j out of range';
45308       }
45309
45310       function rmd160_K2(j) {
45311         return (0 <= j && j <= 15) ? 0x50a28be6 :
45312           (16 <= j && j <= 31) ? 0x5c4dd124 :
45313           (32 <= j && j <= 47) ? 0x6d703ef3 :
45314           (48 <= j && j <= 63) ? 0x7a6d76e9 :
45315           (64 <= j && j <= 79) ? 0x00000000 :
45316           'rmd160_K2: j out of range';
45317       }
45318     }
45319   };
45320
45321   // exposes Hashes
45322   (function(window, undefined) {
45323     var freeExports = false;
45324     if (typeof exports === 'object') {
45325       freeExports = exports;
45326       if (exports && typeof commonjsGlobal === 'object' && commonjsGlobal && commonjsGlobal === commonjsGlobal.global) {
45327         window = commonjsGlobal;
45328       }
45329     }
45330
45331     if (typeof define === 'function' && typeof define.amd === 'object' && define.amd) {
45332       // define as an anonymous module, so, through path mapping, it can be aliased
45333       define(function() {
45334         return Hashes;
45335       });
45336     } else if (freeExports) {
45337       // in Node.js or RingoJS v0.8.0+
45338       if (typeof module === 'object' && module && module.exports === freeExports) {
45339         module.exports = Hashes;
45340       }
45341       // in Narwhal or RingoJS v0.7.0-
45342       else {
45343         freeExports.Hashes = Hashes;
45344       }
45345     } else {
45346       // in a browser or Rhino
45347       window.Hashes = Hashes;
45348     }
45349   }(this));
45350 }()); // IIFE
45351 });
45352
45353 var immutable = extend$2;
45354
45355 var hasOwnProperty = Object.prototype.hasOwnProperty;
45356
45357 function extend$2() {
45358     var target = {};
45359
45360     for (var i = 0; i < arguments.length; i++) {
45361         var source = arguments[i];
45362
45363         for (var key in source) {
45364             if (hasOwnProperty.call(source, key)) {
45365                 target[key] = source[key];
45366             }
45367         }
45368     }
45369
45370     return target
45371 }
45372
45373 var hashes = hashes$1;
45374 var xtend$1 = immutable;
45375 var sha1 = new hashes.SHA1();
45376
45377 var ohauth$1 = {};
45378
45379 ohauth$1.qsString = function(obj) {
45380     return Object.keys(obj).sort().map(function(key) {
45381         return ohauth$1.percentEncode(key) + '=' +
45382             ohauth$1.percentEncode(obj[key]);
45383     }).join('&');
45384 };
45385
45386 ohauth$1.stringQs = function(str) {
45387     return str.split('&').filter(function (pair) {
45388         return pair !== '';
45389     }).reduce(function(obj, pair){
45390         var parts = pair.split('=');
45391         obj[decodeURIComponent(parts[0])] = (null === parts[1]) ?
45392             '' : decodeURIComponent(parts[1]);
45393         return obj;
45394     }, {});
45395 };
45396
45397 ohauth$1.rawxhr = function(method, url, data, headers, callback) {
45398     var xhr = new XMLHttpRequest(),
45399         twoHundred = /^20\d$/;
45400     xhr.onreadystatechange = function() {
45401         if (4 === xhr.readyState && 0 !== xhr.status) {
45402             if (twoHundred.test(xhr.status)) callback(null, xhr);
45403             else return callback(xhr, null);
45404         }
45405     };
45406     xhr.onerror = function(e) { return callback(e, null); };
45407     xhr.open(method, url, true);
45408     for (var h in headers) xhr.setRequestHeader(h, headers[h]);
45409     xhr.send(data);
45410     return xhr;
45411 };
45412
45413 ohauth$1.xhr = function(method, url, auth, data, options, callback) {
45414     var headers = (options && options.header) || {
45415         'Content-Type': 'application/x-www-form-urlencoded'
45416     };
45417     headers.Authorization = 'OAuth ' + ohauth$1.authHeader(auth);
45418     return ohauth$1.rawxhr(method, url, data, headers, callback);
45419 };
45420
45421 ohauth$1.nonce = function() {
45422     for (var o = ''; o.length < 6;) {
45423         o += '0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz'[Math.floor(Math.random() * 61)];
45424     }
45425     return o;
45426 };
45427
45428 ohauth$1.authHeader = function(obj) {
45429     return Object.keys(obj).sort().map(function(key) {
45430         return encodeURIComponent(key) + '="' + encodeURIComponent(obj[key]) + '"';
45431     }).join(', ');
45432 };
45433
45434 ohauth$1.timestamp = function() { return ~~((+new Date()) / 1000); };
45435
45436 ohauth$1.percentEncode = function(s) {
45437     return encodeURIComponent(s)
45438         .replace(/\!/g, '%21').replace(/\'/g, '%27')
45439         .replace(/\*/g, '%2A').replace(/\(/g, '%28').replace(/\)/g, '%29');
45440 };
45441
45442 ohauth$1.baseString = function(method, url, params) {
45443     if (params.oauth_signature) delete params.oauth_signature;
45444     return [
45445         method,
45446         ohauth$1.percentEncode(url),
45447         ohauth$1.percentEncode(ohauth$1.qsString(params))].join('&');
45448 };
45449
45450 ohauth$1.signature = function(oauth_secret, token_secret, baseString) {
45451     return sha1.b64_hmac(
45452         ohauth$1.percentEncode(oauth_secret) + '&' +
45453         ohauth$1.percentEncode(token_secret),
45454         baseString);
45455 };
45456
45457 /**
45458  * Takes an options object for configuration (consumer_key,
45459  * consumer_secret, version, signature_method, token, token_secret)
45460  * and returns a function that generates the Authorization header
45461  * for given data.
45462  *
45463  * The returned function takes these parameters:
45464  * - method: GET/POST/...
45465  * - uri: full URI with protocol, port, path and query string
45466  * - extra_params: any extra parameters (that are passed in the POST data),
45467  *   can be an object or a from-urlencoded string.
45468  *
45469  * Returned function returns full OAuth header with "OAuth" string in it.
45470  */
45471
45472 ohauth$1.headerGenerator = function(options) {
45473     options = options || {};
45474     var consumer_key = options.consumer_key || '',
45475         consumer_secret = options.consumer_secret || '',
45476         signature_method = options.signature_method || 'HMAC-SHA1',
45477         version = options.version || '1.0',
45478         token = options.token || '',
45479         token_secret = options.token_secret || '';
45480
45481     return function(method, uri, extra_params) {
45482         method = method.toUpperCase();
45483         if (typeof extra_params === 'string' && extra_params.length > 0) {
45484             extra_params = ohauth$1.stringQs(extra_params);
45485         }
45486
45487         var uri_parts = uri.split('?', 2),
45488         base_uri = uri_parts[0];
45489
45490         var query_params = uri_parts.length === 2 ?
45491             ohauth$1.stringQs(uri_parts[1]) : {};
45492
45493         var oauth_params = {
45494             oauth_consumer_key: consumer_key,
45495             oauth_signature_method: signature_method,
45496             oauth_version: version,
45497             oauth_timestamp: ohauth$1.timestamp(),
45498             oauth_nonce: ohauth$1.nonce()
45499         };
45500
45501         if (token) oauth_params.oauth_token = token;
45502
45503         var all_params = xtend$1({}, oauth_params, query_params, extra_params),
45504             base_str = ohauth$1.baseString(method, base_uri, all_params);
45505
45506         oauth_params.oauth_signature = ohauth$1.signature(consumer_secret, token_secret, base_str);
45507
45508         return 'OAuth ' + ohauth$1.authHeader(oauth_params);
45509     };
45510 };
45511
45512 var index$12 = ohauth$1;
45513
45514 var store$1 = createCommonjsModule(function (module, exports) {
45515 "use strict"
45516 // Module export pattern from
45517 // https://github.com/umdjs/umd/blob/master/returnExports.js
45518 ;(function (root, factory) {
45519     if (typeof define === 'function' && define.amd) {
45520         // AMD. Register as an anonymous module.
45521         define([], factory);
45522     } else if (typeof exports === 'object') {
45523         // Node. Does not work with strict CommonJS, but
45524         // only CommonJS-like environments that support module.exports,
45525         // like Node.
45526         module.exports = factory();
45527     } else {
45528         // Browser globals (root is window)
45529         root.store = factory();
45530   }
45531 }(commonjsGlobal, function () {
45532         
45533         // Store.js
45534         var store = {},
45535                 win = (typeof window != 'undefined' ? window : commonjsGlobal),
45536                 doc = win.document,
45537                 localStorageName = 'localStorage',
45538                 scriptTag = 'script',
45539                 storage;
45540
45541         store.disabled = false;
45542         store.version = '1.3.20';
45543         store.set = function(key, value) {};
45544         store.get = function(key, defaultVal) {};
45545         store.has = function(key) { return store.get(key) !== undefined };
45546         store.remove = function(key) {};
45547         store.clear = function() {};
45548         store.transact = function(key, defaultVal, transactionFn) {
45549                 if (transactionFn == null) {
45550                         transactionFn = defaultVal;
45551                         defaultVal = null;
45552                 }
45553                 if (defaultVal == null) {
45554                         defaultVal = {};
45555                 }
45556                 var val = store.get(key, defaultVal);
45557                 transactionFn(val);
45558                 store.set(key, val);
45559         };
45560         store.getAll = function() {};
45561         store.forEach = function() {};
45562
45563         store.serialize = function(value) {
45564                 return JSON.stringify(value)
45565         };
45566         store.deserialize = function(value) {
45567                 if (typeof value != 'string') { return undefined }
45568                 try { return JSON.parse(value) }
45569                 catch(e) { return value || undefined }
45570         };
45571
45572         // Functions to encapsulate questionable FireFox 3.6.13 behavior
45573         // when about.config::dom.storage.enabled === false
45574         // See https://github.com/marcuswestin/store.js/issues#issue/13
45575         function isLocalStorageNameSupported() {
45576                 try { return (localStorageName in win && win[localStorageName]) }
45577                 catch(err) { return false }
45578         }
45579
45580         if (isLocalStorageNameSupported()) {
45581                 storage = win[localStorageName];
45582                 store.set = function(key, val) {
45583                         if (val === undefined) { return store.remove(key) }
45584                         storage.setItem(key, store.serialize(val));
45585                         return val
45586                 };
45587                 store.get = function(key, defaultVal) {
45588                         var val = store.deserialize(storage.getItem(key));
45589                         return (val === undefined ? defaultVal : val)
45590                 };
45591                 store.remove = function(key) { storage.removeItem(key); };
45592                 store.clear = function() { storage.clear(); };
45593                 store.getAll = function() {
45594                         var ret = {};
45595                         store.forEach(function(key, val) {
45596                                 ret[key] = val;
45597                         });
45598                         return ret
45599                 };
45600                 store.forEach = function(callback) {
45601                         for (var i=0; i<storage.length; i++) {
45602                                 var key = storage.key(i);
45603                                 callback(key, store.get(key));
45604                         }
45605                 };
45606         } else if (doc && doc.documentElement.addBehavior) {
45607                 var storageOwner,
45608                         storageContainer;
45609                 // Since #userData storage applies only to specific paths, we need to
45610                 // somehow link our data to a specific path.  We choose /favicon.ico
45611                 // as a pretty safe option, since all browsers already make a request to
45612                 // this URL anyway and being a 404 will not hurt us here.  We wrap an
45613                 // iframe pointing to the favicon in an ActiveXObject(htmlfile) object
45614                 // (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx)
45615                 // since the iframe access rules appear to allow direct access and
45616                 // manipulation of the document element, even for a 404 page.  This
45617                 // document can be used instead of the current document (which would
45618                 // have been limited to the current path) to perform #userData storage.
45619                 try {
45620                         storageContainer = new ActiveXObject('htmlfile');
45621                         storageContainer.open();
45622                         storageContainer.write('<'+scriptTag+'>document.w=window</'+scriptTag+'><iframe src="/favicon.ico"></iframe>');
45623                         storageContainer.close();
45624                         storageOwner = storageContainer.w.frames[0].document;
45625                         storage = storageOwner.createElement('div');
45626                 } catch(e) {
45627                         // somehow ActiveXObject instantiation failed (perhaps some special
45628                         // security settings or otherwse), fall back to per-path storage
45629                         storage = doc.createElement('div');
45630                         storageOwner = doc.body;
45631                 }
45632                 var withIEStorage = function(storeFunction) {
45633                         return function() {
45634                                 var args = Array.prototype.slice.call(arguments, 0);
45635                                 args.unshift(storage);
45636                                 // See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx
45637                                 // and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx
45638                                 storageOwner.appendChild(storage);
45639                                 storage.addBehavior('#default#userData');
45640                                 storage.load(localStorageName);
45641                                 var result = storeFunction.apply(store, args);
45642                                 storageOwner.removeChild(storage);
45643                                 return result
45644                         }
45645                 };
45646
45647                 // In IE7, keys cannot start with a digit or contain certain chars.
45648                 // See https://github.com/marcuswestin/store.js/issues/40
45649                 // See https://github.com/marcuswestin/store.js/issues/83
45650                 var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g");
45651                 var ieKeyFix = function(key) {
45652                         return key.replace(/^d/, '___$&').replace(forbiddenCharsRegex, '___')
45653                 };
45654                 store.set = withIEStorage(function(storage, key, val) {
45655                         key = ieKeyFix(key);
45656                         if (val === undefined) { return store.remove(key) }
45657                         storage.setAttribute(key, store.serialize(val));
45658                         storage.save(localStorageName);
45659                         return val
45660                 });
45661                 store.get = withIEStorage(function(storage, key, defaultVal) {
45662                         key = ieKeyFix(key);
45663                         var val = store.deserialize(storage.getAttribute(key));
45664                         return (val === undefined ? defaultVal : val)
45665                 });
45666                 store.remove = withIEStorage(function(storage, key) {
45667                         key = ieKeyFix(key);
45668                         storage.removeAttribute(key);
45669                         storage.save(localStorageName);
45670                 });
45671                 store.clear = withIEStorage(function(storage) {
45672                         var attributes = storage.XMLDocument.documentElement.attributes;
45673                         storage.load(localStorageName);
45674                         for (var i=attributes.length-1; i>=0; i--) {
45675                                 storage.removeAttribute(attributes[i].name);
45676                         }
45677                         storage.save(localStorageName);
45678                 });
45679                 store.getAll = function(storage) {
45680                         var ret = {};
45681                         store.forEach(function(key, val) {
45682                                 ret[key] = val;
45683                         });
45684                         return ret
45685                 };
45686                 store.forEach = withIEStorage(function(storage, callback) {
45687                         var attributes = storage.XMLDocument.documentElement.attributes;
45688                         for (var i=0, attr; attr=attributes[i]; ++i) {
45689                                 callback(attr.name, store.deserialize(storage.getAttribute(attr.name)));
45690                         }
45691                 });
45692         }
45693
45694         try {
45695                 var testKey = '__storejs__';
45696                 store.set(testKey, testKey);
45697                 if (store.get(testKey) != testKey) { store.disabled = true; }
45698                 store.remove(testKey);
45699         } catch(e) {
45700                 store.disabled = true;
45701         }
45702         store.enabled = !store.disabled;
45703         
45704         return store
45705 }));
45706 });
45707
45708 var ohauth = index$12;
45709 var xtend = immutable;
45710 var store = store$1;
45711
45712 // # osm-auth
45713 //
45714 // This code is only compatible with IE10+ because the [XDomainRequest](http://bit.ly/LfO7xo)
45715 // object, IE<10's idea of [CORS](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing),
45716 // does not support custom headers, which this uses everywhere.
45717 var index$11 = function(o) {
45718
45719     var oauth = {};
45720
45721     // authenticated users will also have a request token secret, but it's
45722     // not used in transactions with the server
45723     oauth.authenticated = function() {
45724         return !!(token('oauth_token') && token('oauth_token_secret'));
45725     };
45726
45727     oauth.logout = function() {
45728         token('oauth_token', '');
45729         token('oauth_token_secret', '');
45730         token('oauth_request_token_secret', '');
45731         return oauth;
45732     };
45733
45734     // TODO: detect lack of click event
45735     oauth.authenticate = function(callback) {
45736         if (oauth.authenticated()) return callback();
45737
45738         oauth.logout();
45739
45740         // ## Getting a request token
45741         var params = timenonce(getAuth(o)),
45742             url = o.url + '/oauth/request_token';
45743
45744         params.oauth_signature = ohauth.signature(
45745             o.oauth_secret, '',
45746             ohauth.baseString('POST', url, params));
45747
45748         if (!o.singlepage) {
45749             // Create a 600x550 popup window in the center of the screen
45750             var w = 600, h = 550,
45751                 settings = [
45752                     ['width', w], ['height', h],
45753                     ['left', screen.width / 2 - w / 2],
45754                     ['top', screen.height / 2 - h / 2]].map(function(x) {
45755                         return x.join('=');
45756                     }).join(','),
45757                 popup = window.open('about:blank', 'oauth_window', settings);
45758         }
45759
45760         // Request a request token. When this is complete, the popup
45761         // window is redirected to OSM's authorization page.
45762         ohauth.xhr('POST', url, params, null, {}, reqTokenDone);
45763         o.loading();
45764
45765         function reqTokenDone(err, xhr) {
45766             o.done();
45767             if (err) return callback(err);
45768             var resp = ohauth.stringQs(xhr.response);
45769             token('oauth_request_token_secret', resp.oauth_token_secret);
45770             var authorize_url = o.url + '/oauth/authorize?' + ohauth.qsString({
45771                 oauth_token: resp.oauth_token,
45772                 oauth_callback: location.href.replace('index.html', '')
45773                     .replace(/#.*/, '').replace(location.search, '') + o.landing
45774             });
45775
45776             if (o.singlepage) {
45777                 location.href = authorize_url;
45778             } else {
45779                 popup.location = authorize_url;
45780             }
45781         }
45782
45783         // Called by a function in a landing page, in the popup window. The
45784         // window closes itself.
45785         window.authComplete = function(token) {
45786             var oauth_token = ohauth.stringQs(token.split('?')[1]);
45787             get_access_token(oauth_token.oauth_token);
45788             delete window.authComplete;
45789         };
45790
45791         // ## Getting an request token
45792         //
45793         // At this point we have an `oauth_token`, brought in from a function
45794         // call on a landing page popup.
45795         function get_access_token(oauth_token) {
45796             var url = o.url + '/oauth/access_token',
45797                 params = timenonce(getAuth(o)),
45798                 request_token_secret = token('oauth_request_token_secret');
45799             params.oauth_token = oauth_token;
45800             params.oauth_signature = ohauth.signature(
45801                 o.oauth_secret,
45802                 request_token_secret,
45803                 ohauth.baseString('POST', url, params));
45804
45805             // ## Getting an access token
45806             //
45807             // The final token required for authentication. At this point
45808             // we have a `request token secret`
45809             ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
45810             o.loading();
45811         }
45812
45813         function accessTokenDone(err, xhr) {
45814             o.done();
45815             if (err) return callback(err);
45816             var access_token = ohauth.stringQs(xhr.response);
45817             token('oauth_token', access_token.oauth_token);
45818             token('oauth_token_secret', access_token.oauth_token_secret);
45819             callback(null, oauth);
45820         }
45821     };
45822
45823     oauth.bootstrapToken = function(oauth_token, callback) {
45824         // ## Getting an request token
45825         // At this point we have an `oauth_token`, brought in from a function
45826         // call on a landing page popup.
45827         function get_access_token(oauth_token) {
45828             var url = o.url + '/oauth/access_token',
45829                 params = timenonce(getAuth(o)),
45830                 request_token_secret = token('oauth_request_token_secret');
45831             params.oauth_token = oauth_token;
45832             params.oauth_signature = ohauth.signature(
45833                 o.oauth_secret,
45834                 request_token_secret,
45835                 ohauth.baseString('POST', url, params));
45836
45837             // ## Getting an access token
45838             // The final token required for authentication. At this point
45839             // we have a `request token secret`
45840             ohauth.xhr('POST', url, params, null, {}, accessTokenDone);
45841             o.loading();
45842         }
45843
45844         function accessTokenDone(err, xhr) {
45845             o.done();
45846             if (err) return callback(err);
45847             var access_token = ohauth.stringQs(xhr.response);
45848             token('oauth_token', access_token.oauth_token);
45849             token('oauth_token_secret', access_token.oauth_token_secret);
45850             callback(null, oauth);
45851         }
45852
45853         get_access_token(oauth_token);
45854     };
45855
45856     // # xhr
45857     //
45858     // A single XMLHttpRequest wrapper that does authenticated calls if the
45859     // user has logged in.
45860     oauth.xhr = function(options, callback) {
45861         if (!oauth.authenticated()) {
45862             if (o.auto) {
45863                 return oauth.authenticate(run);
45864             } else {
45865                 callback('not authenticated', null);
45866                 return;
45867             }
45868         } else {
45869             return run();
45870         }
45871
45872         function run() {
45873             var params = timenonce(getAuth(o)),
45874                 oauth_token_secret = token('oauth_token_secret'),
45875                 url = (options.prefix !== false) ? o.url + options.path : options.path,
45876                 url_parts = url.replace(/#.*$/, '').split('?', 2),
45877                 base_url = url_parts[0],
45878                 query = (url_parts.length === 2) ? url_parts[1] : '';
45879
45880             // https://tools.ietf.org/html/rfc5849#section-3.4.1.3.1
45881             if ((!options.options || !options.options.header ||
45882                 options.options.header['Content-Type'] === 'application/x-www-form-urlencoded') &&
45883                 options.content) {
45884                 params = xtend(params, ohauth.stringQs(options.content));
45885             }
45886
45887             params.oauth_token = token('oauth_token');
45888             params.oauth_signature = ohauth.signature(
45889                 o.oauth_secret,
45890                 oauth_token_secret,
45891                 ohauth.baseString(options.method, base_url, xtend(params, ohauth.stringQs(query)))
45892             );
45893
45894             return ohauth.xhr(options.method, url, params, options.content, options.options, done);
45895         }
45896
45897         function done(err, xhr) {
45898             if (err) return callback(err);
45899             else if (xhr.responseXML) return callback(err, xhr.responseXML);
45900             else return callback(err, xhr.response);
45901         }
45902     };
45903
45904     // pre-authorize this object, if we can just get a token and token_secret
45905     // from the start
45906     oauth.preauth = function(c) {
45907         if (!c) return;
45908         if (c.oauth_token) token('oauth_token', c.oauth_token);
45909         if (c.oauth_token_secret) token('oauth_token_secret', c.oauth_token_secret);
45910         return oauth;
45911     };
45912
45913     oauth.options = function(_) {
45914         if (!arguments.length) return o;
45915
45916         o = _;
45917         o.url = o.url || 'http://www.openstreetmap.org';
45918         o.landing = o.landing || 'land.html';
45919         o.singlepage = o.singlepage || false;
45920
45921         // Optional loading and loading-done functions for nice UI feedback.
45922         // by default, no-ops
45923         o.loading = o.loading || function() {};
45924         o.done = o.done || function() {};
45925
45926         return oauth.preauth(o);
45927     };
45928
45929     // 'stamp' an authentication object from `getAuth()`
45930     // with a [nonce](http://en.wikipedia.org/wiki/Cryptographic_nonce)
45931     // and timestamp
45932     function timenonce(o) {
45933         o.oauth_timestamp = ohauth.timestamp();
45934         o.oauth_nonce = ohauth.nonce();
45935         return o;
45936     }
45937
45938     // get/set tokens. These are prefixed with the base URL so that `osm-auth`
45939     // can be used with multiple APIs and the keys in `localStorage`
45940     // will not clash
45941     var token;
45942
45943     if (store.enabled) {
45944         token = function (x, y) {
45945             if (arguments.length === 1) return store.get(o.url + x);
45946             else if (arguments.length === 2) return store.set(o.url + x, y);
45947         };
45948     } else {
45949         var storage = {};
45950         token = function (x, y) {
45951             if (arguments.length === 1) return storage[o.url + x];
45952             else if (arguments.length === 2) return storage[o.url + x] = y;
45953         };
45954     }
45955
45956     // Get an authentication object. If you just add and remove properties
45957     // from a single object, you'll need to use `delete` to make sure that
45958     // it doesn't contain undesired properties for authentication
45959     function getAuth(o) {
45960         return {
45961             oauth_consumer_key: o.oauth_consumer_key,
45962             oauth_signature_method: 'HMAC-SHA1'
45963         };
45964     }
45965
45966     // potentially pre-authorize
45967     oauth.options(o);
45968
45969     return oauth;
45970 };
45971
45972 var JXON = new (function () {
45973   var
45974     sValueProp = 'keyValue', sAttributesProp = 'keyAttributes', sAttrPref = '@', /* you can customize these values */
45975     aCache = [], rIsNull = /^\s*$/, rIsBool = /^(?:true|false)$/i;
45976
45977   function parseText (sValue) {
45978     if (rIsNull.test(sValue)) { return null; }
45979     if (rIsBool.test(sValue)) { return sValue.toLowerCase() === 'true'; }
45980     if (isFinite(sValue)) { return parseFloat(sValue); }
45981     if (isFinite(Date.parse(sValue))) { return new Date(sValue); }
45982     return sValue;
45983   }
45984
45985   function EmptyTree () { }
45986   EmptyTree.prototype.toString = function () { return 'null'; };
45987   EmptyTree.prototype.valueOf = function () { return null; };
45988
45989   function objectify (vValue) {
45990     return vValue === null ? new EmptyTree() : vValue instanceof Object ? vValue : new vValue.constructor(vValue);
45991   }
45992
45993   function createObjTree (oParentNode, nVerb, bFreeze, bNesteAttr) {
45994     var
45995       nLevelStart = aCache.length, bChildren = oParentNode.hasChildNodes(),
45996       bAttributes = oParentNode.hasAttributes(), bHighVerb = Boolean(nVerb & 2);
45997
45998     var
45999       sProp, vContent, nLength = 0, sCollectedTxt = '',
46000       vResult = bHighVerb ? {} : /* put here the default value for empty nodes: */ true;
46001
46002     if (bChildren) {
46003       for (var oNode, nItem = 0; nItem < oParentNode.childNodes.length; nItem++) {
46004         oNode = oParentNode.childNodes.item(nItem);
46005         if (oNode.nodeType === 4) { sCollectedTxt += oNode.nodeValue; } /* nodeType is 'CDATASection' (4) */
46006         else if (oNode.nodeType === 3) { sCollectedTxt += oNode.nodeValue.trim(); } /* nodeType is 'Text' (3) */
46007         else if (oNode.nodeType === 1 && !oNode.prefix) { aCache.push(oNode); } /* nodeType is 'Element' (1) */
46008       }
46009     }
46010
46011     var nLevelEnd = aCache.length, vBuiltVal = parseText(sCollectedTxt);
46012
46013     if (!bHighVerb && (bChildren || bAttributes)) { vResult = nVerb === 0 ? objectify(vBuiltVal) : {}; }
46014
46015     for (var nElId = nLevelStart; nElId < nLevelEnd; nElId++) {
46016       sProp = aCache[nElId].nodeName.toLowerCase();
46017       vContent = createObjTree(aCache[nElId], nVerb, bFreeze, bNesteAttr);
46018       if (vResult.hasOwnProperty(sProp)) {
46019         if (vResult[sProp].constructor !== Array) { vResult[sProp] = [vResult[sProp]]; }
46020         vResult[sProp].push(vContent);
46021       } else {
46022         vResult[sProp] = vContent;
46023         nLength++;
46024       }
46025     }
46026
46027     if (bAttributes) {
46028       var
46029         nAttrLen = oParentNode.attributes.length,
46030         sAPrefix = bNesteAttr ? '' : sAttrPref, oAttrParent = bNesteAttr ? {} : vResult;
46031
46032       for (var oAttrib, nAttrib = 0; nAttrib < nAttrLen; nLength++, nAttrib++) {
46033         oAttrib = oParentNode.attributes.item(nAttrib);
46034         oAttrParent[sAPrefix + oAttrib.name.toLowerCase()] = parseText(oAttrib.value.trim());
46035       }
46036
46037       if (bNesteAttr) {
46038         if (bFreeze) { Object.freeze(oAttrParent); }
46039         vResult[sAttributesProp] = oAttrParent;
46040         nLength -= nAttrLen - 1;
46041       }
46042     }
46043
46044     if (nVerb === 3 || (nVerb === 2 || nVerb === 1 && nLength > 0) && sCollectedTxt) {
46045       vResult[sValueProp] = vBuiltVal;
46046     } else if (!bHighVerb && nLength === 0 && sCollectedTxt) {
46047       vResult = vBuiltVal;
46048     }
46049
46050     if (bFreeze && (bHighVerb || nLength > 0)) { Object.freeze(vResult); }
46051
46052     aCache.length = nLevelStart;
46053
46054     return vResult;
46055   }
46056
46057   function loadObjTree (oXMLDoc, oParentEl, oParentObj) {
46058     var vValue, oChild;
46059
46060     if (oParentObj instanceof String || oParentObj instanceof Number || oParentObj instanceof Boolean) {
46061       oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toString())); /* verbosity level is 0 */
46062     } else if (oParentObj.constructor === Date) {
46063       oParentEl.appendChild(oXMLDoc.createTextNode(oParentObj.toGMTString()));    
46064     }
46065
46066     for (var sName in oParentObj) {
46067       vValue = oParentObj[sName];
46068       if (isFinite(sName) || vValue instanceof Function) { continue; } /* verbosity level is 0 */
46069       if (sName === sValueProp) {
46070         if (vValue !== null && vValue !== true) { oParentEl.appendChild(oXMLDoc.createTextNode(vValue.constructor === Date ? vValue.toGMTString() : String(vValue))); }
46071       } else if (sName === sAttributesProp) { /* verbosity level is 3 */
46072         for (var sAttrib in vValue) { oParentEl.setAttribute(sAttrib, vValue[sAttrib]); }
46073       } else if (sName.charAt(0) === sAttrPref) {
46074         oParentEl.setAttribute(sName.slice(1), vValue);
46075       } else if (vValue.constructor === Array) {
46076         for (var nItem = 0; nItem < vValue.length; nItem++) {
46077           oChild = oXMLDoc.createElement(sName);
46078           loadObjTree(oXMLDoc, oChild, vValue[nItem]);
46079           oParentEl.appendChild(oChild);
46080         }
46081       } else {
46082         oChild = oXMLDoc.createElement(sName);
46083         if (vValue instanceof Object) {
46084           loadObjTree(oXMLDoc, oChild, vValue);
46085         } else if (vValue !== null && vValue !== true) {
46086           oChild.appendChild(oXMLDoc.createTextNode(vValue.toString()));
46087         }
46088         oParentEl.appendChild(oChild);
46089      }
46090    }
46091   }
46092
46093   this.build = function (oXMLParent, nVerbosity /* optional */, bFreeze /* optional */, bNesteAttributes /* optional */) {
46094     var _nVerb = arguments.length > 1 && typeof nVerbosity === 'number' ? nVerbosity & 3 : /* put here the default verbosity level: */ 1;
46095     return createObjTree(oXMLParent, _nVerb, bFreeze || false, arguments.length > 3 ? bNesteAttributes : _nVerb === 3);    
46096   };
46097
46098   this.unbuild = function (oObjTree) {    
46099     var oNewDoc = document.implementation.createDocument('', '', null);
46100     loadObjTree(oNewDoc, oNewDoc, oObjTree);
46101     return oNewDoc;
46102   };
46103
46104   this.stringify = function (oObjTree) {
46105     return (new XMLSerializer()).serializeToString(JXON.unbuild(oObjTree));
46106   };
46107 })();
46108
46109 // var myObject = JXON.build(doc);
46110 // we got our javascript object! try: alert(JSON.stringify(myObject));
46111
46112 // var newDoc = JXON.unbuild(myObject);
46113 // we got our Document instance! try: alert((new XMLSerializer()).serializeToString(newDoc));
46114
46115 var dispatch$3 = dispatch('authLoading', 'authDone', 'change', 'loading', 'loaded');
46116 var useHttps = window.location.protocol === 'https:';
46117 var protocol = useHttps ? 'https:' : 'http:';
46118 var urlroot = protocol + '//www.openstreetmap.org';
46119 var inflight = {};
46120 var loadedTiles = {};
46121 var tileZoom$1 = 16;
46122 var oauth = index$11({
46123         url: urlroot,
46124         oauth_consumer_key: '5A043yRSEugj4DJ5TljuapfnrflWDte8jTOcWLlT',
46125         oauth_secret: 'aB3jKq1TRsCOUrfOIZ6oQMEDmv2ptV76PA54NGLL',
46126         loading: authLoading,
46127         done: authDone
46128     });
46129 var rateLimitError;
46130 var userDetails;
46131 var off;
46132
46133
46134 function authLoading() {
46135     dispatch$3.call('authLoading');
46136 }
46137
46138
46139 function authDone() {
46140     dispatch$3.call('authDone');
46141 }
46142
46143
46144 function abortRequest$1(i) {
46145     if (i) {
46146         i.abort();
46147     }
46148 }
46149
46150
46151 function getLoc(attrs) {
46152     var lon = attrs.lon && attrs.lon.value,
46153         lat = attrs.lat && attrs.lat.value;
46154     return [parseFloat(lon), parseFloat(lat)];
46155 }
46156
46157
46158 function getNodes(obj) {
46159     var elems = obj.getElementsByTagName('nd'),
46160         nodes = new Array(elems.length);
46161     for (var i = 0, l = elems.length; i < l; i++) {
46162         nodes[i] = 'n' + elems[i].attributes.ref.value;
46163     }
46164     return nodes;
46165 }
46166
46167
46168 function getTags(obj) {
46169     var elems = obj.getElementsByTagName('tag'),
46170         tags = {};
46171     for (var i = 0, l = elems.length; i < l; i++) {
46172         var attrs = elems[i].attributes;
46173         tags[attrs.k.value] = attrs.v.value;
46174     }
46175     return tags;
46176 }
46177
46178
46179 function getMembers(obj) {
46180     var elems = obj.getElementsByTagName('member'),
46181         members = new Array(elems.length);
46182     for (var i = 0, l = elems.length; i < l; i++) {
46183         var attrs = elems[i].attributes;
46184         members[i] = {
46185             id: attrs.type.value[0] + attrs.ref.value,
46186             type: attrs.type.value,
46187             role: attrs.role.value
46188         };
46189     }
46190     return members;
46191 }
46192
46193
46194 function getVisible(attrs) {
46195     return (!attrs.visible || attrs.visible.value !== 'false');
46196 }
46197
46198
46199 var parsers = {
46200     node: function nodeData(obj) {
46201         var attrs = obj.attributes;
46202         return new osmNode({
46203             id: osmEntity$$1.id.fromOSM('node', attrs.id.value),
46204             loc: getLoc(attrs),
46205             version: attrs.version.value,
46206             user: attrs.user && attrs.user.value,
46207             tags: getTags(obj),
46208             visible: getVisible(attrs)
46209         });
46210     },
46211
46212     way: function wayData(obj) {
46213         var attrs = obj.attributes;
46214         return new osmWay({
46215             id: osmEntity$$1.id.fromOSM('way', attrs.id.value),
46216             version: attrs.version.value,
46217             user: attrs.user && attrs.user.value,
46218             tags: getTags(obj),
46219             nodes: getNodes(obj),
46220             visible: getVisible(attrs)
46221         });
46222     },
46223
46224     relation: function relationData(obj) {
46225         var attrs = obj.attributes;
46226         return new osmRelation({
46227             id: osmEntity$$1.id.fromOSM('relation', attrs.id.value),
46228             version: attrs.version.value,
46229             user: attrs.user && attrs.user.value,
46230             tags: getTags(obj),
46231             members: getMembers(obj),
46232             visible: getVisible(attrs)
46233         });
46234     }
46235 };
46236
46237
46238 function parse(xml$$1) {
46239     if (!xml$$1 || !xml$$1.childNodes) return;
46240
46241     var root = xml$$1.childNodes[0],
46242         children = root.childNodes,
46243         entities = [];
46244
46245     for (var i = 0, l = children.length; i < l; i++) {
46246         var child = children[i],
46247             parser = parsers[child.nodeName];
46248         if (parser) {
46249             entities.push(parser(child));
46250         }
46251     }
46252
46253     return entities;
46254 }
46255
46256
46257 var serviceOsm = {
46258
46259     init: function() {
46260         utilRebind(this, dispatch$3, 'on');
46261     },
46262
46263
46264     reset: function() {
46265         userDetails = undefined;
46266         rateLimitError = undefined;
46267         lodash.forEach(inflight, abortRequest$1);
46268         loadedTiles = {};
46269         inflight = {};
46270         return this;
46271     },
46272
46273
46274     changesetURL: function(changesetId) {
46275         return urlroot + '/changeset/' + changesetId;
46276     },
46277
46278
46279     changesetsURL: function(center, zoom$$1) {
46280         var precision = Math.max(0, Math.ceil(Math.log(zoom$$1) / Math.LN2));
46281         return urlroot + '/history#map=' +
46282             Math.floor(zoom$$1) + '/' +
46283             center[1].toFixed(precision) + '/' +
46284             center[0].toFixed(precision);
46285     },
46286
46287
46288     entityURL: function(entity) {
46289         return urlroot + '/' + entity.type + '/' + entity.osmId();
46290     },
46291
46292
46293     userURL: function(username) {
46294         return urlroot + '/user/' + username;
46295     },
46296
46297
46298     loadFromAPI: function(path$$1, callback) {
46299         var that = this;
46300
46301         function done(err, xml$$1) {
46302             var isAuthenticated = that.authenticated();
46303
46304             // 400 Bad Request, 401 Unauthorized, 403 Forbidden
46305             // Logout and retry the request..
46306             if (isAuthenticated && err &&
46307                     (err.status === 400 || err.status === 401 || err.status === 403)) {
46308                 that.logout();
46309                 that.loadFromAPI(path$$1, callback);
46310
46311             // else, no retry..
46312             } else {
46313                 // 509 Bandwidth Limit Exceeded, 429 Too Many Requests
46314                 // Set the rateLimitError flag and trigger a warning..
46315                 if (!isAuthenticated && !rateLimitError && err &&
46316                         (err.status === 509 || err.status === 429)) {
46317                     rateLimitError = err;
46318                     dispatch$3.call('change');
46319                 }
46320
46321                 if (callback) {
46322                     callback(err, parse(xml$$1));
46323                 }
46324             }
46325         }
46326
46327         if (this.authenticated()) {
46328             return oauth.xhr({ method: 'GET', path: path$$1 }, done);
46329         } else {
46330             var url = urlroot + path$$1;
46331             return xml(url).get(done);
46332         }
46333     },
46334
46335
46336     loadEntity: function(id, callback) {
46337         var type = osmEntity$$1.id.type(id),
46338             osmID = osmEntity$$1.id.toOSM(id);
46339
46340         this.loadFromAPI(
46341             '/api/0.6/' + type + '/' + osmID + (type !== 'node' ? '/full' : ''),
46342             function(err, entities) {
46343                 if (callback) callback(err, { data: entities });
46344             }
46345         );
46346     },
46347
46348
46349     loadEntityVersion: function(id, version$$1, callback) {
46350         var type = osmEntity$$1.id.type(id),
46351             osmID = osmEntity$$1.id.toOSM(id);
46352
46353         this.loadFromAPI(
46354             '/api/0.6/' + type + '/' + osmID + '/' + version$$1,
46355             function(err, entities) {
46356                 if (callback) callback(err, { data: entities });
46357             }
46358         );
46359     },
46360
46361
46362     loadMultiple: function(ids, callback) {
46363         var that = this;
46364         lodash.each(lodash.groupBy(lodash.uniq(ids), osmEntity$$1.id.type), function(v, k) {
46365             var type = k + 's',
46366                 osmIDs = lodash.map(v, osmEntity$$1.id.toOSM);
46367
46368             lodash.each(lodash.chunk(osmIDs, 150), function(arr) {
46369                 that.loadFromAPI(
46370                     '/api/0.6/' + type + '?' + type + '=' + arr.join(),
46371                     function(err, entities) {
46372                         if (callback) callback(err, { data: entities });
46373                     }
46374                 );
46375             });
46376         });
46377     },
46378
46379
46380     authenticated: function() {
46381         return oauth.authenticated();
46382     },
46383
46384
46385     // Generate Changeset XML. Returns a string.
46386     changesetJXON: function(tags) {
46387         return {
46388             osm: {
46389                 changeset: {
46390                     tag: lodash.map(tags, function(value, key) {
46391                         return { '@k': key, '@v': value };
46392                     }),
46393                     '@version': 0.6,
46394                     '@generator': 'iD'
46395                 }
46396             }
46397         };
46398     },
46399
46400
46401     // Generate [osmChange](http://wiki.openstreetmap.org/wiki/OsmChange)
46402     // XML. Returns a string.
46403     osmChangeJXON: function(changeset_id, changes) {
46404         function nest$$1(x, order) {
46405             var groups = {};
46406             for (var i = 0; i < x.length; i++) {
46407                 var tagName = Object.keys(x[i])[0];
46408                 if (!groups[tagName]) groups[tagName] = [];
46409                 groups[tagName].push(x[i][tagName]);
46410             }
46411             var ordered = {};
46412             order.forEach(function(o) {
46413                 if (groups[o]) ordered[o] = groups[o];
46414             });
46415             return ordered;
46416         }
46417
46418         function rep(entity) {
46419             return entity.asJXON(changeset_id);
46420         }
46421
46422         return {
46423             osmChange: {
46424                 '@version': 0.6,
46425                 '@generator': 'iD',
46426                 'create': nest$$1(changes.created.map(rep), ['node', 'way', 'relation']),
46427                 'modify': nest$$1(changes.modified.map(rep), ['node', 'way', 'relation']),
46428                 'delete': lodash.extend(nest$$1(changes.deleted.map(rep), ['relation', 'way', 'node']), {'@if-unused': true})
46429             }
46430         };
46431     },
46432
46433
46434     changesetTags: function(version$$1, comment, imageryUsed) {
46435         var detected = utilDetect(),
46436             tags = {
46437                 created_by: ('iD ' + version$$1).substr(0, 255),
46438                 imagery_used: imageryUsed.join(';').substr(0, 255),
46439                 host: detected.host.substr(0, 255),
46440                 locale: detected.locale.substr(0, 255)
46441             };
46442
46443         if (comment) {
46444             tags.comment = comment.substr(0, 255);
46445         }
46446
46447         return tags;
46448     },
46449
46450
46451     putChangeset: function(changes, version$$1, comment, imageryUsed, callback) {
46452         var that = this;
46453         oauth.xhr({
46454                 method: 'PUT',
46455                 path: '/api/0.6/changeset/create',
46456                 options: { header: { 'Content-Type': 'text/xml' } },
46457                 content: JXON.stringify(that.changesetJXON(that.changesetTags(version$$1, comment, imageryUsed)))
46458             }, function(err, changeset_id) {
46459                 if (err) return callback(err);
46460                 oauth.xhr({
46461                     method: 'POST',
46462                     path: '/api/0.6/changeset/' + changeset_id + '/upload',
46463                     options: { header: { 'Content-Type': 'text/xml' } },
46464                     content: JXON.stringify(that.osmChangeJXON(changeset_id, changes))
46465                 }, function(err) {
46466                     if (err) return callback(err);
46467                     // POST was successful, safe to call the callback.
46468                     // Still attempt to close changeset, but ignore response because #2667
46469                     // Add delay to allow for postgres replication #1646 #2678
46470                     window.setTimeout(function() { callback(null, changeset_id); }, 2500);
46471                     oauth.xhr({
46472                         method: 'PUT',
46473                         path: '/api/0.6/changeset/' + changeset_id + '/close',
46474                         options: { header: { 'Content-Type': 'text/xml' } }
46475                     }, function() { return true; });
46476                 });
46477             });
46478     },
46479
46480
46481     userDetails: function(callback) {
46482         if (userDetails) {
46483             callback(undefined, userDetails);
46484             return;
46485         }
46486
46487         function done(err, user_details) {
46488             if (err) return callback(err);
46489
46490             var u = user_details.getElementsByTagName('user')[0],
46491                 img = u.getElementsByTagName('img'),
46492                 image_url = '';
46493
46494             if (img && img[0] && img[0].getAttribute('href')) {
46495                 image_url = img[0].getAttribute('href');
46496             }
46497
46498             userDetails = {
46499                 display_name: u.attributes.display_name.value,
46500                 image_url: image_url,
46501                 id: u.attributes.id.value
46502             };
46503
46504             callback(undefined, userDetails);
46505         }
46506
46507         oauth.xhr({ method: 'GET', path: '/api/0.6/user/details' }, done);
46508     },
46509
46510
46511     userChangesets: function(callback) {
46512         this.userDetails(function(err, user) {
46513             if (err) {
46514                 callback(err);
46515                 return;
46516             }
46517
46518             function done(err, changesets) {
46519                 if (err) {
46520                     callback(err);
46521                 } else {
46522                     callback(undefined, Array.prototype.map.call(changesets.getElementsByTagName('changeset'),
46523                         function (changeset) {
46524                             return { tags: getTags(changeset) };
46525                         }
46526                     ));
46527                 }
46528             }
46529
46530             oauth.xhr({ method: 'GET', path: '/api/0.6/changesets?user=' + user.id }, done);
46531         });
46532     },
46533
46534
46535     status: function(callback) {
46536         function done(capabilities) {
46537             if (rateLimitError) {
46538                 callback(rateLimitError, 'rateLimited');
46539             } else {
46540                 var apiStatus = capabilities.getElementsByTagName('status'),
46541                     val = apiStatus[0].getAttribute('api');
46542                 callback(undefined, val);
46543             }
46544         }
46545         xml(urlroot + '/api/capabilities').get()
46546             .on('load', done)
46547             .on('error', callback);
46548     },
46549
46550
46551     tileZoom: function(_) {
46552         if (!arguments.length) return tileZoom$1;
46553         tileZoom$1 = _;
46554         return this;
46555     },
46556
46557
46558     loadTiles: function(projection, dimensions, callback) {
46559         if (off) return;
46560
46561         var that = this,
46562             s = projection.scale() * 2 * Math.PI,
46563             z = Math.max(Math.log(s) / Math.log(2) - 8, 0),
46564             ts = 256 * Math.pow(2, z - tileZoom$1),
46565             origin = [
46566                 s / 2 - projection.translate()[0],
46567                 s / 2 - projection.translate()[1]
46568             ];
46569
46570         var tiles = d3geoTile()
46571             .scaleExtent([tileZoom$1, tileZoom$1])
46572             .scale(s)
46573             .size(dimensions)
46574             .translate(projection.translate())()
46575             .map(function(tile) {
46576                 var x = tile[0] * ts - origin[0],
46577                     y = tile[1] * ts - origin[1];
46578
46579                 return {
46580                     id: tile.toString(),
46581                     extent: geoExtent$$1(
46582                         projection.invert([x, y + ts]),
46583                         projection.invert([x + ts, y]))
46584                 };
46585             });
46586
46587         lodash.filter(inflight, function(v, i) {
46588             var wanted = lodash.find(tiles, function(tile) {
46589                 return i === tile.id;
46590             });
46591             if (!wanted) delete inflight[i];
46592             return !wanted;
46593         }).map(abortRequest$1);
46594
46595         tiles.forEach(function(tile) {
46596             var id = tile.id;
46597
46598             if (loadedTiles[id] || inflight[id]) return;
46599
46600             if (lodash.isEmpty(inflight)) {
46601                 dispatch$3.call('loading');
46602             }
46603
46604             inflight[id] = that.loadFromAPI(
46605                 '/api/0.6/map?bbox=' + tile.extent.toParam(),
46606                 function(err, parsed) {
46607                     delete inflight[id];
46608                     if (!err) {
46609                         loadedTiles[id] = true;
46610                     }
46611
46612                     if (callback) {
46613                         callback(err, lodash.extend({ data: parsed }, tile));
46614                     }
46615
46616                     if (lodash.isEmpty(inflight)) {
46617                         dispatch$3.call('loaded');
46618                     }
46619                 }
46620             );
46621         });
46622     },
46623
46624
46625     switch: function(options) {
46626         urlroot = options.urlroot;
46627
46628         oauth.options(lodash.extend({
46629             url: urlroot,
46630             loading: authLoading,
46631             done: authDone
46632         }, options));
46633         dispatch$3.call('change');
46634         this.reset();
46635         return this;
46636     },
46637
46638
46639     toggle: function(_) {
46640         off = !_;
46641         return this;
46642     },
46643
46644
46645     loadedTiles: function(_) {
46646         if (!arguments.length) return loadedTiles;
46647         loadedTiles = _;
46648         return this;
46649     },
46650
46651
46652     logout: function() {
46653         userDetails = undefined;
46654         oauth.logout();
46655         dispatch$3.call('change');
46656         return this;
46657     },
46658
46659
46660     authenticate: function(callback) {
46661         userDetails = undefined;
46662         function done(err, res) {
46663             rateLimitError = undefined;
46664             dispatch$3.call('change');
46665             if (callback) callback(err, res);
46666         }
46667         return oauth.authenticate(done);
46668     }
46669 };
46670
46671 var endpoint$1 = 'https://taginfo.openstreetmap.org/api/4/';
46672 var taginfoCache = {};
46673 var tag_sorts = {
46674         point: 'count_nodes',
46675         vertex: 'count_nodes',
46676         area: 'count_ways',
46677         line: 'count_ways'
46678     };
46679 var tag_sort_members = {
46680         point: 'count_node_members',
46681         vertex: 'count_node_members',
46682         area: 'count_way_members',
46683         line: 'count_way_members',
46684         relation: 'count_relation_members'
46685     };
46686 var tag_filters = {
46687         point: 'nodes',
46688         vertex: 'nodes',
46689         area: 'ways',
46690         line: 'ways'
46691     };
46692 var tag_members_fractions = {
46693         point: 'count_node_members_fraction',
46694         vertex: 'count_node_members_fraction',
46695         area: 'count_way_members_fraction',
46696         line: 'count_way_members_fraction',
46697         relation: 'count_relation_members_fraction'
46698     };
46699
46700
46701 function sets(parameters, n, o) {
46702     if (parameters.geometry && o[parameters.geometry]) {
46703         parameters[n] = o[parameters.geometry];
46704     }
46705     return parameters;
46706 }
46707
46708
46709 function setFilter(parameters) {
46710     return sets(parameters, 'filter', tag_filters);
46711 }
46712
46713
46714 function setSort(parameters) {
46715     return sets(parameters, 'sortname', tag_sorts);
46716 }
46717
46718
46719 function setSortMembers(parameters) {
46720     return sets(parameters, 'sortname', tag_sort_members);
46721 }
46722
46723
46724 function clean(parameters) {
46725     return lodash.omit(parameters, 'geometry', 'debounce');
46726 }
46727
46728
46729 function filterKeys(type) {
46730     var count_type = type ? 'count_' + type : 'count_all';
46731     return function(d) {
46732         return parseFloat(d[count_type]) > 2500 || d.in_wiki;
46733     };
46734 }
46735
46736
46737 function filterMultikeys(prefix) {
46738     return function(d) {
46739         // d.key begins with prefix, and d.key contains no additional ':'s
46740         var re = new RegExp('^' + prefix + '(.*)$');
46741         var matches = d.key.match(re) || [];
46742         return (matches.length === 2 && matches[1].indexOf(':') === -1);
46743     };
46744 }
46745
46746
46747 function filterValues(allowUpperCase) {
46748     return function(d) {
46749         if (d.value.match(/[;,]/) !== null) return false;  // exclude some punctuation
46750         if (!allowUpperCase && d.value.match(/[A-Z*]/) !== null) return false;  // exclude uppercase letters
46751         return parseFloat(d.fraction) > 0.0 || d.in_wiki;
46752     };
46753 }
46754
46755
46756 function filterRoles(geometry) {
46757     return function(d) {
46758         if (d.role === '') return false; // exclude empty role
46759         if (d.role.match(/[A-Z*;,]/) !== null) return false;  // exclude uppercase letters and some punctuation
46760         return parseFloat(d[tag_members_fractions[geometry]]) > 0.0;
46761     };
46762 }
46763
46764
46765 function valKey(d) {
46766     return {
46767         value: d.key,
46768         title: d.key
46769     };
46770 }
46771
46772
46773 function valKeyDescription(d) {
46774     return {
46775         value: d.value,
46776         title: d.description || d.value
46777     };
46778 }
46779
46780
46781 function roleKey(d) {
46782     return {
46783         value: d.role,
46784         title: d.role
46785     };
46786 }
46787
46788
46789 // sort keys with ':' lower than keys without ':'
46790 function sortKeys(a, b) {
46791     return (a.key.indexOf(':') === -1 && b.key.indexOf(':') !== -1) ? -1
46792         : (a.key.indexOf(':') !== -1 && b.key.indexOf(':') === -1) ? 1
46793         : 0;
46794 }
46795
46796
46797 var debounced = lodash.debounce(json, 100, true);
46798
46799
46800 function request$1(url, debounce, callback) {
46801     if (taginfoCache[url]) {
46802         callback(null, taginfoCache[url]);
46803     } else if (debounce) {
46804         debounced(url, done);
46805     } else {
46806         json(url, done);
46807     }
46808
46809     function done(err, data) {
46810         if (!err) {
46811             taginfoCache[url] = data;
46812         }
46813         callback(err, data);
46814     }
46815 }
46816
46817
46818 var serviceTaginfo = {
46819
46820     init: function() { taginfoCache = {}; },
46821     reset: function() { taginfoCache = {}; },
46822
46823
46824     keys: function(parameters, callback) {
46825         var debounce = parameters.debounce;
46826         parameters = clean(setSort(parameters));
46827         request$1(endpoint$1 + 'keys/all?' +
46828             utilQsString(lodash.extend({
46829                 rp: 10,
46830                 sortname: 'count_all',
46831                 sortorder: 'desc',
46832                 page: 1
46833             }, parameters)), debounce, function(err, d) {
46834                 if (err) {
46835                     callback(err);
46836                 } else {
46837                     var f = filterKeys(parameters.filter);
46838                     callback(null, d.data.filter(f).sort(sortKeys).map(valKey));
46839                 }
46840             }
46841         );
46842     },
46843
46844
46845     multikeys: function(parameters, callback) {
46846         var debounce = parameters.debounce;
46847         parameters = clean(setSort(parameters));
46848         var prefix = parameters.query;
46849         request$1(endpoint$1 + 'keys/all?' +
46850             utilQsString(lodash.extend({
46851                 rp: 25,
46852                 sortname: 'count_all',
46853                 sortorder: 'desc',
46854                 page: 1
46855             }, parameters)), debounce, function(err, d) {
46856                 if (err) {
46857                     callback(err);
46858                 } else {
46859                     var f = filterMultikeys(prefix);
46860                     callback(null, d.data.filter(f).map(valKey));
46861                 }
46862             }
46863         );
46864     },
46865
46866
46867     values: function(parameters, callback) {
46868         var debounce = parameters.debounce;
46869         parameters = clean(setSort(setFilter(parameters)));
46870         request$1(endpoint$1 + 'key/values?' +
46871             utilQsString(lodash.extend({
46872                 rp: 25,
46873                 sortname: 'count_all',
46874                 sortorder: 'desc',
46875                 page: 1
46876             }, parameters)), debounce, function(err, d) {
46877                 if (err) {
46878                     callback(err);
46879                 } else {
46880                     // In most cases we prefer taginfo value results with lowercase letters.
46881                     // A few OSM keys expect values to contain uppercase values (see #3377).
46882                     // This is not an exhaustive list (e.g. `name` also has uppercase values)
46883                     // but these are the fields where taginfo value lookup is most useful.
46884                     var re = /network|taxon|genus|species/;
46885                     var allowUpperCase = (parameters.key.match(re) !== null);
46886                     var f = filterValues(allowUpperCase);
46887                     callback(null, d.data.filter(f).map(valKeyDescription));
46888                 }
46889             }
46890         );
46891     },
46892
46893
46894     roles: function(parameters, callback) {
46895         var debounce = parameters.debounce;
46896         var geometry = parameters.geometry;
46897         parameters = clean(setSortMembers(parameters));
46898         request$1(endpoint$1 + 'relation/roles?' +
46899             utilQsString(lodash.extend({
46900                 rp: 25,
46901                 sortname: 'count_all_members',
46902                 sortorder: 'desc',
46903                 page: 1
46904             }, parameters)), debounce, function(err, d) {
46905                 if (err) {
46906                     callback(err);
46907                 } else {
46908                     var f = filterRoles(geometry);
46909                     callback(null, d.data.filter(f).map(roleKey));
46910                 }
46911             }
46912         );
46913     },
46914
46915
46916     docs: function(parameters, callback) {
46917         var debounce = parameters.debounce;
46918         parameters = clean(setSort(parameters));
46919
46920         var path$$1 = 'key/wiki_pages?';
46921         if (parameters.value) path$$1 = 'tag/wiki_pages?';
46922         else if (parameters.rtype) path$$1 = 'relation/wiki_pages?';
46923
46924         request$1(endpoint$1 + path$$1 + utilQsString(parameters), debounce, function(err, d) {
46925             if (err) {
46926                 callback(err);
46927             } else {
46928                 callback(null, d.data);
46929             }
46930         });
46931     },
46932
46933
46934     endpoint: function(_) {
46935         if (!arguments.length) return endpoint$1;
46936         endpoint$1 = _;
46937         return this;
46938     }
46939
46940 };
46941
46942 var jsonpCache = {};
46943 window.jsonpCache = jsonpCache;
46944
46945 function jsonpRequest(url, callback) {
46946
46947   if (window.JSONP_FIX) {
46948     if (window.JSONP_DELAY === 0) {
46949       callback(window.JSONP_FIX);
46950     } else {
46951       setTimeout(function() {
46952         callback(window.JSONP_FIX);
46953       }, window.JSONP_DELAY || 0);
46954     }
46955     return;
46956   }
46957
46958   function rand() {
46959     var chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',
46960       c = '', i = -1;
46961     while (++i < 15) c += chars.charAt(Math.floor(Math.random() * 52));
46962     return c;
46963   }
46964
46965   function create(url) {
46966     var e = url.match(/callback=(\w+)/),
46967       c = e ? e[1] : rand();
46968     jsonpCache[c] = function(data) {
46969       callback(data);
46970       delete jsonpCache[c];
46971       script.remove();
46972     };
46973     return 'jsonpCache.' + c;
46974   }
46975
46976   var cb = create(url),
46977     script = select('head')
46978     .append('script')
46979     .attr('type', 'text/javascript')
46980     .attr('src', url.replace(/(\{|%7B)callback(\}|%7D)/, cb));
46981 }
46982
46983 var endpoint$2 = 'https://www.wikidata.org/w/api.php?';
46984
46985 var serviceWikidata = {
46986
46987     init: function() {},
46988     reset: function() {},
46989
46990
46991     // Given a Wikipedia language and article title, return an array of
46992     // corresponding Wikidata entities.
46993     itemsByTitle: function(lang, title, callback) {
46994         if (!title) {
46995             callback('', {});
46996             return;
46997         }
46998
46999         lang = lang || 'en';
47000         jsonpRequest(endpoint$2 + utilQsString({
47001             action: 'wbgetentities',
47002             format: 'json',
47003             sites: lang.replace(/-/g, '_') + 'wiki',
47004             titles: title,
47005             languages: 'en', // shrink response by filtering to one language
47006             callback: '{callback}'
47007         }), function(data) {
47008             if (!data || data.error) {
47009                 callback('', {});
47010             } else {
47011                 callback(title, data.entities || {});
47012             }
47013         });
47014     }
47015
47016 };
47017
47018 var endpoint$3 = 'https://en.wikipedia.org/w/api.php?';
47019
47020 var serviceWikipedia = {
47021
47022     init: function() {},
47023     reset: function() {},
47024
47025
47026     search: function(lang, query, callback) {
47027         if (!query) {
47028             callback('', []);
47029             return;
47030         }
47031
47032         lang = lang || 'en';
47033         jsonpRequest(endpoint$3.replace('en', lang) +
47034             utilQsString({
47035                 action: 'query',
47036                 list: 'search',
47037                 srlimit: '10',
47038                 srinfo: 'suggestion',
47039                 format: 'json',
47040                 callback: '{callback}',
47041                 srsearch: query
47042             }), function(data) {
47043                 if (!data || !data.query || !data.query.search || data.error) {
47044                     callback('', []);
47045                 } else {
47046                     var results = data.query.search.map(function(d) { return d.title; });
47047                     callback(query, results);
47048                 }
47049             }
47050         );
47051     },
47052
47053
47054     suggestions: function(lang, query, callback) {
47055         if (!query) {
47056             callback('', []);
47057             return;
47058         }
47059
47060         lang = lang || 'en';
47061         jsonpRequest(endpoint$3.replace('en', lang) +
47062             utilQsString({
47063                 action: 'opensearch',
47064                 namespace: 0,
47065                 suggest: '',
47066                 format: 'json',
47067                 callback: '{callback}',
47068                 search: query
47069             }), function(data) {
47070                 if (!data || data.error) {
47071                     callback('', []);
47072                 } else {
47073                     callback(data[0], data[1] || []);
47074                 }
47075             }
47076         );
47077     },
47078
47079
47080     translations: function(lang, title, callback) {
47081         if (!title) {
47082             callback({});
47083             return;
47084         }
47085
47086         jsonpRequest(endpoint$3.replace('en', lang) +
47087             utilQsString({
47088                 action: 'query',
47089                 prop: 'langlinks',
47090                 format: 'json',
47091                 callback: '{callback}',
47092                 lllimit: 500,
47093                 titles: title
47094             }), function(data) {
47095                 if (!data || !data.query || !data.query.pages || data.error) {
47096                     callback({});
47097                 } else {
47098                     var list = data.query.pages[Object.keys(data.query.pages)[0]],
47099                         translations = {};
47100                     if (list && list.langlinks) {
47101                         list.langlinks.forEach(function(d) {
47102                             translations[d.lang] = d['*'];
47103                         });
47104                     }
47105                     callback(translations);
47106                 }
47107             }
47108         );
47109     }
47110
47111 };
47112
47113 var services = {
47114     mapillary: serviceMapillary,
47115     nominatim: serviceNominatim,
47116     osm: serviceOsm,
47117     taginfo: serviceTaginfo,
47118     wikidata: serviceWikidata,
47119     wikipedia: serviceWikipedia
47120 };
47121
47122 function svgMapillaryImages(projection, context, dispatch$$1) {
47123     var throttledRedraw = lodash.throttle(function () { dispatch$$1.call('change'); }, 1000),
47124         minZoom = 12,
47125         minViewfieldZoom = 16,
47126         layer = select(null),
47127         _mapillary;
47128
47129
47130     function init() {
47131         if (svgMapillaryImages.initialized) return;  // run once
47132         svgMapillaryImages.enabled = false;
47133         svgMapillaryImages.initialized = true;
47134     }
47135
47136
47137     function getMapillary() {
47138         if (services.mapillary && !_mapillary) {
47139             _mapillary = services.mapillary;
47140             _mapillary.event.on('loadedImages', throttledRedraw);
47141         } else if (!services.mapillary && _mapillary) {
47142             _mapillary = null;
47143         }
47144
47145         return _mapillary;
47146     }
47147
47148
47149     function showLayer() {
47150         var mapillary = getMapillary();
47151         if (!mapillary) return;
47152
47153         mapillary.loadViewer(context);
47154         editOn();
47155
47156         layer
47157             .style('opacity', 0)
47158             .transition()
47159             .duration(500)
47160             .style('opacity', 1)
47161             .on('end', function () { dispatch$$1.call('change'); });
47162     }
47163
47164
47165     function hideLayer() {
47166         var mapillary = getMapillary();
47167         if (mapillary) {
47168             mapillary.hideViewer();
47169         }
47170
47171         throttledRedraw.cancel();
47172
47173         layer
47174             .transition()
47175             .duration(500)
47176             .style('opacity', 0)
47177             .on('end', editOff);
47178     }
47179
47180
47181     function editOn() {
47182         layer.style('display', 'block');
47183     }
47184
47185
47186     function editOff() {
47187         layer.selectAll('.viewfield-group').remove();
47188         layer.style('display', 'none');
47189     }
47190
47191
47192     function click(d) {
47193         var mapillary = getMapillary();
47194         if (!mapillary) return;
47195
47196         context.map().centerEase(d.loc);
47197
47198         mapillary
47199             .selectedImage(d.key, true)
47200             .updateViewer(d.key, context)
47201             .showViewer();
47202     }
47203
47204
47205     function transform(d) {
47206         var t = svgPointTransform(projection)(d);
47207         if (d.ca) t += ' rotate(' + Math.floor(d.ca) + ',0,0)';
47208         return t;
47209     }
47210
47211
47212     function update() {
47213         var mapillary = getMapillary(),
47214             data = (mapillary ? mapillary.images(projection) : []),
47215             imageKey = mapillary ? mapillary.selectedImage() : null;
47216
47217         var markers = layer.selectAll('.viewfield-group')
47218             .data(data, function(d) { return d.key; });
47219
47220         markers.exit()
47221             .remove();
47222
47223         var enter = markers.enter()
47224             .append('g')
47225             .attr('class', 'viewfield-group')
47226             .classed('selected', function(d) { return d.key === imageKey; })
47227             .on('click', click);
47228
47229         markers = markers
47230             .merge(enter)
47231             .attr('transform', transform);
47232
47233
47234        var viewfields = markers.selectAll('.viewfield')
47235             .data(~~context.map().zoom() >= minViewfieldZoom ? [0] : []);
47236
47237         viewfields.exit()
47238             .remove();
47239
47240         viewfields.enter()
47241             .append('path')
47242             .attr('class', 'viewfield')
47243             .attr('transform', 'scale(1.5,1.5),translate(-8, -13)')
47244             .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');
47245
47246         markers.selectAll('circle')
47247             .data([0])
47248             .enter()
47249             .append('circle')
47250             .attr('dx', '0')
47251             .attr('dy', '0')
47252             .attr('r', '6');
47253     }
47254
47255
47256     function drawImages(selection$$1) {
47257         var enabled = svgMapillaryImages.enabled,
47258             mapillary = getMapillary();
47259
47260         layer = selection$$1.selectAll('.layer-mapillary-images')
47261             .data(mapillary ? [0] : []);
47262
47263         layer.exit()
47264             .remove();
47265
47266         layer = layer.enter()
47267             .append('g')
47268             .attr('class', 'layer-mapillary-images')
47269             .style('display', enabled ? 'block' : 'none')
47270             .merge(layer);
47271
47272         if (enabled) {
47273             if (mapillary && ~~context.map().zoom() >= minZoom) {
47274                 editOn();
47275                 update();
47276                 mapillary.loadImages(projection);
47277             } else {
47278                 editOff();
47279             }
47280         }
47281     }
47282
47283
47284     drawImages.enabled = function(_) {
47285         if (!arguments.length) return svgMapillaryImages.enabled;
47286         svgMapillaryImages.enabled = _;
47287         if (svgMapillaryImages.enabled) {
47288             showLayer();
47289         } else {
47290             hideLayer();
47291         }
47292         dispatch$$1.call('change');
47293         return this;
47294     };
47295
47296
47297     drawImages.supported = function() {
47298         return !!getMapillary();
47299     };
47300
47301
47302     init();
47303     return drawImages;
47304 }
47305
47306 function svgMapillarySigns(projection, context, dispatch$$1) {
47307     var throttledRedraw = lodash.throttle(function () { dispatch$$1.call('change'); }, 1000),
47308         minZoom = 12,
47309         layer = select(null),
47310         _mapillary;
47311
47312
47313     function init() {
47314         if (svgMapillarySigns.initialized) return;  // run once
47315         svgMapillarySigns.enabled = false;
47316         svgMapillarySigns.initialized = true;
47317     }
47318
47319
47320     function getMapillary() {
47321         if (services.mapillary && !_mapillary) {
47322             _mapillary = services.mapillary;
47323             _mapillary.event.on('loadedSigns', throttledRedraw);
47324         } else if (!services.mapillary && _mapillary) {
47325             _mapillary = null;
47326         }
47327         return _mapillary;
47328     }
47329
47330
47331     function showLayer() {
47332         editOn();
47333     }
47334
47335
47336     function hideLayer() {
47337         throttledRedraw.cancel();
47338         editOff();
47339     }
47340
47341
47342     function editOn() {
47343         layer.style('display', 'block');
47344     }
47345
47346
47347     function editOff() {
47348         layer.selectAll('.icon-sign').remove();
47349         layer.style('display', 'none');
47350     }
47351
47352
47353     function click(d) {
47354         var mapillary = getMapillary();
47355         if (!mapillary) return;
47356
47357         context.map().centerEase(d.loc);
47358
47359         mapillary
47360             .selectedImage(d.key, true)
47361             .updateViewer(d.key, context)
47362             .showViewer();
47363     }
47364
47365
47366     function update() {
47367         var mapillary = getMapillary(),
47368             data = (mapillary ? mapillary.signs(projection) : []),
47369             imageKey = mapillary ? mapillary.selectedImage() : null;
47370
47371         var signs = layer.selectAll('.icon-sign')
47372             .data(data, function(d) { return d.key; });
47373
47374         signs.exit()
47375             .remove();
47376
47377         var enter = signs.enter()
47378             .append('foreignObject')
47379             .attr('class', 'icon-sign')
47380             .attr('width', '32px')      // for Firefox
47381             .attr('height', '32px')     // for Firefox
47382             .classed('selected', function(d) { return d.key === imageKey; })
47383             .on('click', click);
47384
47385         enter
47386             .append('xhtml:body')
47387             .attr('class', 'icon-sign-body')
47388             .html(mapillary.signHTML);
47389
47390         signs
47391             .merge(enter)
47392             .attr('x', function(d) { return projection(d.loc)[0] - 16; })   // offset by -16px to
47393             .attr('y', function(d) { return projection(d.loc)[1] - 16; });  // center signs on loc
47394     }
47395
47396
47397     function drawSigns(selection$$1) {
47398         var enabled = svgMapillarySigns.enabled,
47399             mapillary = getMapillary();
47400
47401         layer = selection$$1.selectAll('.layer-mapillary-signs')
47402             .data(mapillary ? [0] : []);
47403
47404         layer.exit()
47405             .remove();
47406
47407         layer = layer.enter()
47408             .append('g')
47409             .attr('class', 'layer-mapillary-signs')
47410             .style('display', enabled ? 'block' : 'none')
47411             .merge(layer);
47412
47413         if (enabled) {
47414             if (mapillary && ~~context.map().zoom() >= minZoom) {
47415                 editOn();
47416                 update();
47417                 mapillary.loadSigns(context, projection);
47418             } else {
47419                 editOff();
47420             }
47421         }
47422     }
47423
47424
47425     drawSigns.enabled = function(_) {
47426         if (!arguments.length) return svgMapillarySigns.enabled;
47427         svgMapillarySigns.enabled = _;
47428         if (svgMapillarySigns.enabled) {
47429             showLayer();
47430         } else {
47431             hideLayer();
47432         }
47433         dispatch$$1.call('change');
47434         return this;
47435     };
47436
47437
47438     drawSigns.supported = function() {
47439         var mapillary = getMapillary();
47440         return (mapillary && mapillary.signsSupported());
47441     };
47442
47443
47444     init();
47445     return drawSigns;
47446 }
47447
47448 function svgOsm() {
47449     return function drawOsm(selection) {
47450         var layers = selection.selectAll('.layer-osm')
47451             .data(['areas', 'lines', 'hit', 'halo', 'label']);
47452
47453         layers.enter()
47454             .append('g')
47455             .attr('class', function(d) { return 'layer-osm layer-' + d; });
47456     };
47457 }
47458
47459 function svgLayers(projection, context) {
47460     var dispatch$$1 = dispatch('change'),
47461         svg = select(null),
47462         layers = [
47463             { id: 'osm', layer: svgOsm(projection, context, dispatch$$1) },
47464             { id: 'gpx', layer: svgGpx(projection, context, dispatch$$1) },
47465             { id: 'mapillary-images', layer: svgMapillaryImages(projection, context, dispatch$$1) },
47466             { id: 'mapillary-signs',  layer: svgMapillarySigns(projection, context, dispatch$$1) },
47467             { id: 'debug', layer: svgDebug(projection, context, dispatch$$1) }
47468         ];
47469
47470
47471     function drawLayers(selection$$1) {
47472         svg = selection$$1.selectAll('.surface')
47473             .data([0]);
47474
47475         svg = svg.enter()
47476             .append('svg')
47477             .attr('class', 'surface')
47478             .merge(svg);
47479
47480         var defs = svg.selectAll('.surface-defs')
47481             .data([0]);
47482
47483         defs.enter()
47484             .append('defs')
47485             .attr('class', 'surface-defs');
47486
47487         var groups = svg.selectAll('.data-layer')
47488             .data(layers);
47489
47490         groups.exit()
47491             .remove();
47492
47493         groups.enter()
47494             .append('g')
47495             .attr('class', function(d) { return 'data-layer data-layer-' + d.id; })
47496             .merge(groups)
47497             .each(function(d) { select(this).call(d.layer); });
47498     }
47499
47500
47501     drawLayers.all = function() {
47502         return layers;
47503     };
47504
47505
47506     drawLayers.layer = function(id) {
47507         var obj = lodash.find(layers, function(o) {return o.id === id;});
47508         return obj && obj.layer;
47509     };
47510
47511
47512     drawLayers.only = function(what) {
47513         var arr = [].concat(what);
47514         drawLayers.remove(lodash.difference(lodash.map(layers, 'id'), arr));
47515         return this;
47516     };
47517
47518
47519     drawLayers.remove = function(what) {
47520         var arr = [].concat(what);
47521         arr.forEach(function(id) {
47522             layers = lodash.reject(layers, function(o) {return o.id === id;});
47523         });
47524         dispatch$$1.call('change');
47525         return this;
47526     };
47527
47528
47529     drawLayers.add = function(what) {
47530         var arr = [].concat(what);
47531         arr.forEach(function(obj) {
47532             if ('id' in obj && 'layer' in obj) {
47533                 layers.push(obj);
47534             }
47535         });
47536         dispatch$$1.call('change');
47537         return this;
47538     };
47539
47540
47541     drawLayers.dimensions = function(_) {
47542         if (!arguments.length) return utilGetDimensions(svg);
47543         utilSetDimensions(svg, _);
47544         return this;
47545     };
47546
47547
47548     return utilRebind(drawLayers, dispatch$$1, 'on');
47549 }
47550
47551 function svgLines$$1(projection) {
47552     var detected = utilDetect();
47553
47554     var highway_stack = {
47555         motorway: 0,
47556         motorway_link: 1,
47557         trunk: 2,
47558         trunk_link: 3,
47559         primary: 4,
47560         primary_link: 5,
47561         secondary: 6,
47562         tertiary: 7,
47563         unclassified: 8,
47564         residential: 9,
47565         service: 10,
47566         footway: 11
47567     };
47568
47569     function waystack(a, b) {
47570         var as = 0, bs = 0;
47571         if (a.tags.highway) { as -= highway_stack[a.tags.highway]; }
47572         if (b.tags.highway) { bs -= highway_stack[b.tags.highway]; }
47573         return as - bs;
47574     }
47575
47576
47577     return function drawLines(selection$$1, graph, entities, filter) {
47578         var ways = [], pathdata = {}, onewaydata = {},
47579             getPath = svgPath(projection, graph);
47580
47581         for (var i = 0; i < entities.length; i++) {
47582             var entity = entities[i],
47583                 outer = osmSimpleMultipolygonOuterMember(entity, graph);
47584             if (outer) {
47585                 ways.push(entity.mergeTags(outer.tags));
47586             } else if (entity.geometry(graph) === 'line') {
47587                 ways.push(entity);
47588             }
47589         }
47590
47591         ways = ways.filter(getPath);
47592
47593         pathdata = lodash.groupBy(ways, function(way) { return way.layer(); });
47594
47595         lodash.forOwn(pathdata, function(v, k) {
47596             onewaydata[k] = lodash(v)
47597                 .filter(function(d) { return d.isOneWay(); })
47598                 .map(svgOneWaySegments(projection, graph, 35))
47599                 .flatten()
47600                 .valueOf();
47601         });
47602
47603         var layer = selection$$1.selectAll('.layer-lines');
47604
47605         var layergroup = layer
47606             .selectAll('g.layergroup')
47607             .data(range(-10, 11));
47608
47609         layergroup = layergroup.enter()
47610             .append('g')
47611             .attr('class', function(d) { return 'layergroup layer' + String(d); })
47612             .merge(layergroup);
47613
47614
47615         var linegroup = layergroup
47616             .selectAll('g.linegroup')
47617             .data(['shadow', 'casing', 'stroke']);
47618
47619         linegroup = linegroup.enter()
47620             .append('g')
47621             .attr('class', function(d) { return 'linegroup line-' + d; })
47622             .merge(linegroup);
47623
47624
47625         var lines = linegroup
47626             .selectAll('path')
47627             .filter(filter)
47628             .data(
47629                 function() { return pathdata[this.parentNode.__data__] || []; },
47630                 osmEntity$$1.key
47631             );
47632
47633         lines.exit()
47634             .remove();
47635
47636         // Optimization: call simple TagClasses only on enter selection. This
47637         // works because osmEntity.key is defined to include the entity v attribute.
47638         lines.enter()
47639             .append('path')
47640             .attr('class', function(d) { return 'way line ' + this.parentNode.__data__ + ' ' + d.id; })
47641             .call(svgTagClasses())
47642             .merge(lines)
47643                 .sort(waystack)
47644                 .attr('d', getPath)
47645                 .call(svgTagClasses().tags(svgRelationMemberTags(graph)));
47646
47647
47648         var onewaygroup = layergroup
47649             .selectAll('g.onewaygroup')
47650             .data(['oneway']);
47651
47652         onewaygroup = onewaygroup.enter()
47653             .append('g')
47654             .attr('class', 'onewaygroup')
47655             .merge(onewaygroup);
47656
47657
47658         var oneways = onewaygroup
47659             .selectAll('path')
47660             .filter(filter)
47661             .data(
47662                 function() { return onewaydata[this.parentNode.__data__] || []; },
47663                 function(d) { return [d.id, d.index]; }
47664             );
47665
47666         oneways.exit()
47667             .remove();
47668
47669         oneways = oneways.enter()
47670             .append('path')
47671             .attr('class', 'oneway')
47672             .attr('marker-mid', 'url(#oneway-marker)')
47673             .merge(oneways)
47674             .attr('d', function(d) { return d.d; });
47675
47676         if (detected.ie) {
47677             oneways.each(function() { this.parentNode.insertBefore(this, this); });
47678         }
47679     };
47680 }
47681
47682 function svgMidpoints$$1(projection, context) {
47683
47684     return function drawMidpoints(selection, graph, entities, filter, extent) {
47685         var poly = extent.polygon(),
47686             midpoints = {};
47687
47688         for (var i = 0; i < entities.length; i++) {
47689             var entity = entities[i];
47690
47691             if (entity.type !== 'way')
47692                 continue;
47693             if (!filter(entity))
47694                 continue;
47695             if (context.selectedIDs().indexOf(entity.id) < 0)
47696                 continue;
47697
47698             var nodes = graph.childNodes(entity);
47699             for (var j = 0; j < nodes.length - 1; j++) {
47700
47701                 var a = nodes[j],
47702                     b = nodes[j + 1],
47703                     id = [a.id, b.id].sort().join('-');
47704
47705                 if (midpoints[id]) {
47706                     midpoints[id].parents.push(entity);
47707                 } else {
47708                     if (geoEuclideanDistance(projection(a.loc), projection(b.loc)) > 40) {
47709                         var point = geoInterp(a.loc, b.loc, 0.5),
47710                             loc = null;
47711
47712                         if (extent.intersects(point)) {
47713                             loc = point;
47714                         } else {
47715                             for (var k = 0; k < 4; k++) {
47716                                 point = geoLineIntersection([a.loc, b.loc], [poly[k], poly[k + 1]]);
47717                                 if (point &&
47718                                     geoEuclideanDistance(projection(a.loc), projection(point)) > 20 &&
47719                                     geoEuclideanDistance(projection(b.loc), projection(point)) > 20)
47720                                 {
47721                                     loc = point;
47722                                     break;
47723                                 }
47724                             }
47725                         }
47726
47727                         if (loc) {
47728                             midpoints[id] = {
47729                                 type: 'midpoint',
47730                                 id: id,
47731                                 loc: loc,
47732                                 edge: [a.id, b.id],
47733                                 parents: [entity]
47734                             };
47735                         }
47736                     }
47737                 }
47738             }
47739         }
47740
47741
47742         function midpointFilter(d) {
47743             if (midpoints[d.id])
47744                 return true;
47745
47746             for (var i = 0; i < d.parents.length; i++) {
47747                 if (filter(d.parents[i])) {
47748                     return true;
47749                 }
47750             }
47751
47752             return false;
47753         }
47754
47755
47756         var layer = selection.selectAll('.layer-hit');
47757
47758         var groups = layer
47759             .selectAll('g.midpoint')
47760             .filter(midpointFilter)
47761             .data(lodash.values(midpoints), function(d) { return d.id; });
47762
47763         groups.exit()
47764             .remove();
47765
47766         var enter = groups.enter()
47767             .insert('g', ':first-child')
47768             .attr('class', 'midpoint');
47769
47770         enter.append('polygon')
47771             .attr('points', '-6,8 10,0 -6,-8')
47772             .attr('class', 'shadow');
47773
47774         enter.append('polygon')
47775             .attr('points', '-3,4 5,0 -3,-4')
47776             .attr('class', 'fill');
47777
47778         groups = groups
47779             .merge(enter)
47780             .attr('transform', function(d) {
47781                 var translate = svgPointTransform(projection),
47782                     a = graph.entity(d.edge[0]),
47783                     b = graph.entity(d.edge[1]),
47784                     angleVal = Math.round(geoAngle(a, b, projection) * (180 / Math.PI));
47785                 return translate(d) + ' rotate(' + angleVal + ')';
47786             })
47787             .call(svgTagClasses().tags(
47788                 function(d) { return d.parents[0].tags; }
47789             ));
47790
47791         // Propagate data bindings.
47792         groups.select('polygon.shadow');
47793         groups.select('polygon.fill');
47794
47795     };
47796 }
47797
47798 function svgOneWaySegments(projection, graph, dt) {
47799     return function(entity) {
47800         var a,
47801             b,
47802             i = 0,
47803             offset = dt,
47804             segments = [],
47805             clip = identity$8().clipExtent(projection.clipExtent()).stream,
47806             coordinates = graph.childNodes(entity).map(function(n) {
47807                 return n.loc;
47808             });
47809
47810         if (entity.tags.oneway === '-1') coordinates.reverse();
47811
47812         geoStream({
47813             type: 'LineString',
47814             coordinates: coordinates
47815         }, projection.stream(clip({
47816             lineStart: function() {},
47817             lineEnd: function() {
47818                 a = null;
47819             },
47820             point: function(x, y) {
47821                 b = [x, y];
47822
47823                 if (a) {
47824                     var span = geoEuclideanDistance(a, b) - offset;
47825
47826                     if (span >= 0) {
47827                         var angle = Math.atan2(b[1] - a[1], b[0] - a[0]),
47828                             dx = dt * Math.cos(angle),
47829                             dy = dt * Math.sin(angle),
47830                             p = [a[0] + offset * Math.cos(angle),
47831                                  a[1] + offset * Math.sin(angle)];
47832
47833                         var segment = 'M' + a[0] + ',' + a[1] +
47834                                       'L' + p[0] + ',' + p[1];
47835
47836                         for (span -= dt; span >= 0; span -= dt) {
47837                             p[0] += dx;
47838                             p[1] += dy;
47839                             segment += 'L' + p[0] + ',' + p[1];
47840                         }
47841
47842                         segment += 'L' + b[0] + ',' + b[1];
47843                         segments.push({id: entity.id, index: i, d: segment});
47844                     }
47845
47846                     offset = -span;
47847                     i++;
47848                 }
47849
47850                 a = b;
47851             }
47852         })));
47853
47854         return segments;
47855     };
47856 }
47857
47858 function svgPath(projection, graph, isArea) {
47859
47860     // Explanation of magic numbers:
47861     // "padding" here allows space for strokes to extend beyond the viewport,
47862     // so that the stroke isn't drawn along the edge of the viewport when
47863     // the shape is clipped.
47864     //
47865     // When drawing lines, pad viewport by 5px.
47866     // When drawing areas, pad viewport by 65px in each direction to allow
47867     // for 60px area fill stroke (see ".fill-partial path.fill" css rule)
47868
47869     var cache = {},
47870         padding = isArea ? 65 : 5,
47871         viewport = projection.clipExtent(),
47872         paddedExtent = [
47873             [viewport[0][0] - padding, viewport[0][1] - padding],
47874             [viewport[1][0] + padding, viewport[1][1] + padding]
47875         ],
47876         clip = identity$8().clipExtent(paddedExtent).stream,
47877         project = projection.stream,
47878         path$$1 = index$5()
47879             .projection({stream: function(output) { return project(clip(output)); }});
47880
47881     return function(entity) {
47882         if (entity.id in cache) {
47883             return cache[entity.id];
47884         } else {
47885             return cache[entity.id] = path$$1(entity.asGeoJSON(graph));
47886         }
47887     };
47888 }
47889
47890 function svgPoints$$1(projection, context) {
47891
47892     function markerPath(selection, klass) {
47893         selection
47894             .attr('class', klass)
47895             .attr('transform', 'translate(-8, -23)')
47896             .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');
47897     }
47898
47899     function sortY(a, b) {
47900         return b.loc[1] - a.loc[1];
47901     }
47902
47903
47904     return function drawPoints(selection, graph, entities, filter) {
47905         var wireframe = context.surface().classed('fill-wireframe'),
47906             points = wireframe ? [] : lodash.filter(entities, function(e) {
47907                 return e.geometry(graph) === 'point';
47908             });
47909
47910         points.sort(sortY);
47911
47912         var layer = selection.selectAll('.layer-hit');
47913
47914         var groups = layer.selectAll('g.point')
47915             .filter(filter)
47916             .data(points, osmEntity$$1.key);
47917
47918         groups.exit()
47919             .remove();
47920
47921         var enter = groups.enter()
47922             .append('g')
47923             .attr('class', function(d) { return 'node point ' + d.id; })
47924             .order();
47925
47926         enter.append('path')
47927             .call(markerPath, 'shadow');
47928
47929         enter.append('path')
47930             .call(markerPath, 'stroke');
47931
47932         enter.append('use')
47933             .attr('transform', 'translate(-6, -20)')
47934             .attr('class', 'icon')
47935             .attr('width', '12px')
47936             .attr('height', '12px');
47937
47938         groups = groups
47939             .merge(enter)
47940             .attr('transform', svgPointTransform(projection))
47941             .call(svgTagClasses());
47942
47943         // Selecting the following implicitly
47944         // sets the data (point entity) on the element
47945         groups.select('.shadow');
47946         groups.select('.stroke');
47947         groups.select('.icon')
47948             .attr('xlink:href', function(entity) {
47949                 var preset = context.presets().match(entity, graph);
47950                 return (preset && preset.icon) ? '#' + preset.icon + '-12' : '';
47951             });
47952     };
47953 }
47954
47955 function svgRelationMemberTags(graph) {
47956     return function(entity) {
47957         var tags = entity.tags;
47958         graph.parentRelations(entity).forEach(function(relation) {
47959             var type = relation.tags.type;
47960             if (type === 'multipolygon' || type === 'boundary') {
47961                 tags = lodash.extend({}, relation.tags, tags);
47962             }
47963         });
47964         return tags;
47965     };
47966 }
47967
47968 function svgTagClasses() {
47969     var primaries = [
47970             'building', 'highway', 'railway', 'waterway', 'aeroway',
47971             'motorway', 'boundary', 'power', 'amenity', 'natural', 'landuse',
47972             'leisure', 'place'
47973         ],
47974         statuses = [
47975             'proposed', 'construction', 'disused', 'abandoned', 'dismantled',
47976             'razed', 'demolished', 'obliterated'
47977         ],
47978         secondaries = [
47979             'oneway', 'bridge', 'tunnel', 'embankment', 'cutting', 'barrier',
47980             'surface', 'tracktype', 'crossing'
47981         ],
47982         tagClassRe = /^tag-/,
47983         tags = function(entity) { return entity.tags; };
47984
47985
47986     var tagClasses = function(selection$$1) {
47987         selection$$1.each(function tagClassesEach(entity) {
47988             var value = this.className,
47989                 classes, primary, status;
47990
47991             if (value.baseVal !== undefined) value = value.baseVal;
47992
47993             classes = value.trim().split(/\s+/).filter(function(name) {
47994                 return name.length && !tagClassRe.test(name);
47995             }).join(' ');
47996
47997             var t = tags(entity), i, k, v;
47998
47999             // pick at most one primary classification tag..
48000             for (i = 0; i < primaries.length; i++) {
48001                 k = primaries[i];
48002                 v = t[k];
48003                 if (!v || v === 'no') continue;
48004
48005                 primary = k;
48006                 if (statuses.indexOf(v) !== -1) {   // e.g. `railway=abandoned`
48007                     status = v;
48008                     classes += ' tag-' + k;
48009                 } else {
48010                     classes += ' tag-' + k + ' tag-' + k + '-' + v;
48011                 }
48012
48013                 break;
48014             }
48015
48016             // add at most one status tag, only if relates to primary tag..
48017             if (!status) {
48018                 for (i = 0; i < statuses.length; i++) {
48019                     k = statuses[i];
48020                     v = t[k];
48021                     if (!v || v === 'no') continue;
48022
48023                     if (v === 'yes') {   // e.g. `railway=rail + abandoned=yes`
48024                         status = k;
48025                     }
48026                     else if (primary && primary === v) {  // e.g. `railway=rail + abandoned=railway`
48027                         status = k;
48028                     } else if (!primary && primaries.indexOf(v) !== -1) {  // e.g. `abandoned=railway`
48029                         status = k;
48030                         primary = v;
48031                         classes += ' tag-' + v;
48032                     }  // else ignore e.g.  `highway=path + abandoned=railway`
48033
48034                     if (status) break;
48035                 }
48036             }
48037
48038             if (status) {
48039                 classes += ' tag-status tag-status-' + status;
48040             }
48041
48042             // add any secondary (structure) tags
48043             for (i = 0; i < secondaries.length; i++) {
48044                 k = secondaries[i];
48045                 v = t[k];
48046                 if (!v || v === 'no') continue;
48047                 classes += ' tag-' + k + ' tag-' + k + '-' + v;
48048             }
48049
48050             // For highways, look for surface tagging..
48051             if (primary === 'highway') {
48052                 var paved = (t.highway !== 'track');
48053                 for (k in t) {
48054                     v = t[k];
48055                     if (k in osmPavedTags) {
48056                         paved = !!osmPavedTags[k][v];
48057                         break;
48058                     }
48059                 }
48060                 if (!paved) {
48061                     classes += ' tag-unpaved';
48062                 }
48063             }
48064
48065             classes = classes.trim();
48066
48067             if (classes !== value) {
48068                 select(this).attr('class', classes);
48069             }
48070         });
48071     };
48072
48073
48074     tagClasses.tags = function(_) {
48075         if (!arguments.length) return tags;
48076         tags = _;
48077         return tagClasses;
48078     };
48079
48080     return tagClasses;
48081 }
48082
48083 function svgTurns(projection) {
48084
48085     return function drawTurns(selection, graph, turns) {
48086
48087         function key(turn) {
48088             return [turn.from.node + turn.via.node + turn.to.node].join('-');
48089         }
48090
48091         function icon(turn) {
48092             var u = turn.u ? '-u' : '';
48093             if (!turn.restriction)
48094                 return '#turn-yes' + u;
48095             var restriction = graph.entity(turn.restriction).tags.restriction;
48096             return '#turn-' +
48097                 (!turn.indirect_restriction && /^only_/.test(restriction) ? 'only' : 'no') + u;
48098         }
48099
48100         var groups = selection.selectAll('.layer-hit').selectAll('g.turn')
48101             .data(turns, key);
48102
48103         groups.exit()
48104             .remove();
48105
48106
48107         var enter = groups.enter()
48108             .append('g')
48109             .attr('class', 'turn');
48110
48111         var nEnter = enter
48112             .filter(function (turn) { return !turn.u; });
48113
48114         nEnter.append('rect')
48115             .attr('transform', 'translate(-22, -12)')
48116             .attr('width', '44')
48117             .attr('height', '24');
48118
48119         nEnter.append('use')
48120             .attr('transform', 'translate(-22, -12)')
48121             .attr('width', '44')
48122             .attr('height', '24');
48123
48124
48125         var uEnter = enter
48126             .filter(function (turn) { return turn.u; });
48127
48128         uEnter.append('circle')
48129             .attr('r', '16');
48130
48131         uEnter.append('use')
48132             .attr('transform', 'translate(-16, -16)')
48133             .attr('width', '32')
48134             .attr('height', '32');
48135
48136
48137         groups = groups
48138             .merge(enter);
48139
48140         groups
48141             .attr('transform', function (turn) {
48142                 var v = graph.entity(turn.via.node),
48143                     t = graph.entity(turn.to.node),
48144                     a = geoAngle(v, t, projection),
48145                     p = projection(v.loc),
48146                     r = turn.u ? 0 : 60;
48147
48148                 return 'translate(' + (r * Math.cos(a) + p[0]) + ',' + (r * Math.sin(a) + p[1]) + ') ' +
48149                     'rotate(' + a * 180 / Math.PI + ')';
48150             });
48151
48152         groups.select('use')
48153             .attr('xlink:href', icon);
48154
48155         groups.select('rect');
48156         groups.select('circle');
48157
48158         return this;
48159     };
48160 }
48161
48162 function svgVertices$$1(projection, context) {
48163     var radiuses = {
48164         //       z16-, z17, z18+, tagged
48165         shadow: [6,    7.5,   7.5,  11.5],
48166         stroke: [2.5,  3.5,   3.5,  7],
48167         fill:   [1,    1.5,   1.5,  1.5]
48168     };
48169
48170     var hover;
48171
48172     function siblingAndChildVertices(ids, graph, extent$$1) {
48173         var vertices = {};
48174
48175         function addChildVertices(entity) {
48176             if (!context.features().isHiddenFeature(entity, graph, entity.geometry(graph))) {
48177                 var i;
48178                 if (entity.type === 'way') {
48179                     for (i = 0; i < entity.nodes.length; i++) {
48180                         addChildVertices(graph.entity(entity.nodes[i]));
48181                     }
48182                 } else if (entity.type === 'relation') {
48183                     for (i = 0; i < entity.members.length; i++) {
48184                         var member = context.hasEntity(entity.members[i].id);
48185                         if (member) {
48186                             addChildVertices(member);
48187                         }
48188                     }
48189                 } else if (entity.intersects(extent$$1, graph)) {
48190                     vertices[entity.id] = entity;
48191                 }
48192             }
48193         }
48194
48195         ids.forEach(function(id) {
48196             var entity = context.hasEntity(id);
48197             if (entity && entity.type === 'node') {
48198                 vertices[entity.id] = entity;
48199                 context.graph().parentWays(entity).forEach(function(entity) {
48200                     addChildVertices(entity);
48201                 });
48202             } else if (entity) {
48203                 addChildVertices(entity);
48204             }
48205         });
48206
48207         return vertices;
48208     }
48209
48210
48211     function draw(selection$$1, vertices, klass, graph, zoom$$1) {
48212
48213         function icon(entity) {
48214             if (entity.id in icons) return icons[entity.id];
48215             icons[entity.id] =
48216                 entity.hasInterestingTags() &&
48217                 context.presets().match(entity, graph).icon;
48218             return icons[entity.id];
48219         }
48220
48221         function setClass(klass) {
48222             return function(entity) {
48223                 this.setAttribute('class', 'node vertex ' + klass + ' ' + entity.id);
48224             };
48225         }
48226
48227         function setAttributes(selection$$1) {
48228             ['shadow','stroke','fill'].forEach(function(klass) {
48229                 var rads = radiuses[klass];
48230                 selection$$1.selectAll('.' + klass)
48231                     .each(function(entity) {
48232                         var i = z && icon(entity),
48233                             c = i ? 0.5 : 0,
48234                             r = rads[i ? 3 : z];
48235                         this.setAttribute('cx', c);
48236                         this.setAttribute('cy', -c);
48237                         this.setAttribute('r', r);
48238                         if (i && klass === 'fill') {
48239                             this.setAttribute('visibility', 'hidden');
48240                         } else {
48241                             this.removeAttribute('visibility');
48242                         }
48243                     });
48244             });
48245
48246             selection$$1.selectAll('use')
48247                 .each(function() {
48248                     if (z) {
48249                         this.removeAttribute('visibility');
48250                     } else {
48251                         this.setAttribute('visibility', 'hidden');
48252                     }
48253                 });
48254         }
48255
48256
48257         var icons = {},
48258             z = (zoom$$1 < 17 ? 0 : zoom$$1 < 18 ? 1 : 2);
48259
48260         var groups = selection$$1
48261             .data(vertices, osmEntity$$1.key);
48262
48263         groups.exit()
48264             .remove();
48265
48266         var enter = groups.enter()
48267             .append('g')
48268             .attr('class', function(d) { return 'node vertex ' + klass + ' ' + d.id; });
48269
48270         enter.append('circle')
48271             .each(setClass('shadow'));
48272
48273         enter.append('circle')
48274             .each(setClass('stroke'));
48275
48276         // Vertices with icons get a `use`.
48277         enter.filter(function(d) { return icon(d); })
48278             .append('use')
48279             .attr('transform', 'translate(-6, -6)')
48280             .attr('xlink:href', function(d) { return '#' + icon(d) + '-12'; })
48281             .attr('width', '12px')
48282             .attr('height', '12px')
48283             .each(setClass('icon'));
48284
48285         // Vertices with tags get a fill.
48286         enter.filter(function(d) { return d.hasInterestingTags(); })
48287             .append('circle')
48288             .each(setClass('fill'));
48289
48290         groups
48291             .merge(enter)
48292             .attr('transform', svgPointTransform(projection))
48293             .classed('shared', function(entity) { return graph.isShared(entity); })
48294             .call(setAttributes);
48295     }
48296
48297
48298     function drawVertices(selection$$1, graph, entities, filter, extent$$1, zoom$$1) {
48299         var selected = siblingAndChildVertices(context.selectedIDs(), graph, extent$$1),
48300             wireframe = context.surface().classed('fill-wireframe'),
48301             vertices = [];
48302
48303         for (var i = 0; i < entities.length; i++) {
48304             var entity = entities[i],
48305                 geometry = entity.geometry(graph);
48306
48307             if (wireframe && geometry === 'point') {
48308                 vertices.push(entity);
48309                 continue;
48310             }
48311
48312             if (geometry !== 'vertex')
48313                 continue;
48314
48315             if (entity.id in selected ||
48316                 entity.hasInterestingTags() ||
48317                 entity.isIntersection(graph)) {
48318                 vertices.push(entity);
48319             }
48320         }
48321
48322         var layer = selection$$1.selectAll('.layer-hit');
48323         layer.selectAll('g.vertex.vertex-persistent')
48324             .filter(filter)
48325             .call(draw, vertices, 'vertex-persistent', graph, zoom$$1);
48326
48327         drawHover(selection$$1, graph, extent$$1, zoom$$1);
48328     }
48329
48330
48331     function drawHover(selection$$1, graph, extent$$1, zoom$$1) {
48332         var hovered = hover ? siblingAndChildVertices([hover.id], graph, extent$$1) : {};
48333         var layer = selection$$1.selectAll('.layer-hit');
48334
48335         layer.selectAll('g.vertex.vertex-hover')
48336             .call(draw, values(hovered), 'vertex-hover', graph, zoom$$1);
48337     }
48338
48339
48340     drawVertices.drawHover = function(selection$$1, graph, target, extent$$1, zoom$$1) {
48341         if (target === hover) return;
48342         hover = target;
48343         drawHover(selection$$1, graph, extent$$1, zoom$$1);
48344     };
48345
48346     return drawVertices;
48347 }
48348
48349 function behaviorEdit(context) {
48350
48351     function edit() {
48352         context.map()
48353             .minzoom(context.minEditableZoom());
48354     }
48355
48356
48357     edit.off = function() {
48358         context.map()
48359             .minzoom(0);
48360     };
48361
48362
48363     return edit;
48364 }
48365
48366 /*
48367    The hover behavior adds the `.hover` class on mouseover to all elements to which
48368    the identical datum is bound, and removes it on mouseout.
48369
48370    The :hover pseudo-class is insufficient for iD's purposes because a datum's visual
48371    representation may consist of several elements scattered throughout the DOM hierarchy.
48372    Only one of these elements can have the :hover pseudo-class, but all of them will
48373    have the .hover class.
48374  */
48375 function behaviorHover() {
48376     var dispatch$$1 = dispatch('hover'),
48377         selection$$1 = select(null),
48378         buttonDown,
48379         altDisables,
48380         target;
48381
48382
48383     function keydown() {
48384         if (altDisables && event.keyCode === d3keybinding.modifierCodes.alt) {
48385             dispatch$$1.call('hover', this, null);
48386             selection$$1.selectAll('.hover')
48387                 .classed('hover-suppressed', true)
48388                 .classed('hover', false);
48389         }
48390     }
48391
48392
48393     function keyup() {
48394         if (altDisables && event.keyCode === d3keybinding.modifierCodes.alt) {
48395             dispatch$$1.call('hover', this, target ? target.id : null);
48396             selection$$1.selectAll('.hover-suppressed')
48397                 .classed('hover-suppressed', false)
48398                 .classed('hover', true);
48399         }
48400     }
48401
48402
48403     var hover = function(__) {
48404         selection$$1 = __;
48405
48406         selection$$1
48407             .on('mouseover.hover', mouseover)
48408             .on('mouseout.hover', mouseout)
48409             .on('mousedown.hover', mousedown);
48410
48411         select(window)
48412             .on('keydown.hover', keydown)
48413             .on('keyup.hover', keyup);
48414
48415
48416         function mouseover() {
48417             if (buttonDown) return;
48418             var target = event.target;
48419             enter(target ? target.__data__ : null);
48420         }
48421
48422
48423         function mouseout() {
48424             if (buttonDown) return;
48425             var target = event.relatedTarget;
48426             enter(target ? target.__data__ : null);
48427         }
48428
48429
48430         function mousedown() {
48431             buttonDown = true;
48432             select(window)
48433                 .on('mouseup.hover', mouseup, true);
48434         }
48435
48436
48437         function mouseup() {
48438             buttonDown = false;
48439             select(window)
48440                 .on('mouseup.hover', null, true);
48441         }
48442
48443
48444         function enter(d) {
48445             if (d === target) return;
48446             target = d;
48447
48448             selection$$1.selectAll('.hover')
48449                 .classed('hover', false);
48450             selection$$1.selectAll('.hover-suppressed')
48451                 .classed('hover-suppressed', false);
48452
48453             if (target instanceof osmEntity$$1) {
48454                 var selector$$1 = '.' + target.id;
48455
48456                 if (target.type === 'relation') {
48457                     target.members.forEach(function(member) {
48458                         selector$$1 += ', .' + member.id;
48459                     });
48460                 }
48461
48462                 var suppressed = altDisables && event && event.altKey;
48463
48464                 selection$$1.selectAll(selector$$1)
48465                     .classed(suppressed ? 'hover-suppressed' : 'hover', true);
48466
48467                 dispatch$$1.call('hover', this, target.id);
48468             } else {
48469                 dispatch$$1.call('hover', this, null);
48470             }
48471         }
48472
48473     };
48474
48475
48476     hover.off = function(selection$$1) {
48477         selection$$1.selectAll('.hover')
48478             .classed('hover', false);
48479         selection$$1.selectAll('.hover-suppressed')
48480             .classed('hover-suppressed', false);
48481
48482         selection$$1
48483             .on('mouseover.hover', null)
48484             .on('mouseout.hover', null)
48485             .on('mousedown.hover', null);
48486
48487         select(window)
48488             .on('keydown.hover', null)
48489             .on('keyup.hover', null);
48490     };
48491
48492
48493     hover.altDisables = function(_) {
48494         if (!arguments.length) return altDisables;
48495         altDisables = _;
48496         return hover;
48497     };
48498
48499
48500     return utilRebind(hover, dispatch$$1, 'on');
48501 }
48502
48503 function behaviorTail() {
48504     var text$$1,
48505         container,
48506         xmargin = 25,
48507         tooltipSize = [0, 0],
48508         selectionSize = [0, 0];
48509
48510
48511     function tail(selection$$1) {
48512         if (!text$$1) return;
48513
48514         select(window)
48515             .on('resize.tail', function() { selectionSize = utilGetDimensions(selection$$1); });
48516
48517         container = select(document.body)
48518             .append('div')
48519             .style('display', 'none')
48520             .attr('class', 'tail tooltip-inner');
48521
48522         container.append('div')
48523             .text(text$$1);
48524
48525         selection$$1
48526             .on('mousemove.tail', mousemove)
48527             .on('mouseenter.tail', mouseenter)
48528             .on('mouseleave.tail', mouseleave);
48529
48530         container
48531             .on('mousemove.tail', mousemove);
48532
48533         tooltipSize = utilGetDimensions(container);
48534         selectionSize = utilGetDimensions(selection$$1);
48535
48536
48537         function show() {
48538             container.style('display', 'block');
48539             tooltipSize = utilGetDimensions(container);
48540         }
48541
48542
48543         function mousemove() {
48544             if (container.style('display') === 'none') show();
48545             var xoffset = ((event.clientX + tooltipSize[0] + xmargin) > selectionSize[0]) ?
48546                 -tooltipSize[0] - xmargin : xmargin;
48547             container.classed('left', xoffset > 0);
48548             utilSetTransform(container, event.clientX + xoffset, event.clientY);
48549         }
48550
48551
48552         function mouseleave() {
48553             if (event.relatedTarget !== container.node()) {
48554                 container.style('display', 'none');
48555             }
48556         }
48557
48558
48559         function mouseenter() {
48560             if (event.relatedTarget !== container.node()) {
48561                 show();
48562             }
48563         }
48564     }
48565
48566
48567     tail.off = function(selection$$1) {
48568         if (!text$$1) return;
48569
48570         container
48571             .on('mousemove.tail', null)
48572             .remove();
48573
48574         selection$$1
48575             .on('mousemove.tail', null)
48576             .on('mouseenter.tail', null)
48577             .on('mouseleave.tail', null);
48578
48579         select(window)
48580             .on('resize.tail', null);
48581     };
48582
48583
48584     tail.text = function(_) {
48585         if (!arguments.length) return text$$1;
48586         text$$1 = _;
48587         return tail;
48588     };
48589
48590
48591     return tail;
48592 }
48593
48594 behaviorDraw.usedTails = {};
48595 behaviorDraw.disableSpace = false;
48596 behaviorDraw.lastSpace = null;
48597
48598
48599 function behaviorDraw(context) {
48600     var dispatch$$1 = dispatch('move', 'click', 'clickWay',
48601             'clickNode', 'undo', 'cancel', 'finish'),
48602         keybinding = d3keybinding('draw'),
48603         hover = behaviorHover(context)
48604             .altDisables(true)
48605             .on('hover', context.ui().sidebar.hover),
48606         tail = behaviorTail(),
48607         edit = behaviorEdit(context),
48608         closeTolerance = 4,
48609         tolerance = 12,
48610         mouseLeave = false,
48611         lastMouse = null,
48612         cached = behaviorDraw;
48613
48614
48615     function datum() {
48616         if (event.altKey) return {};
48617
48618         if (event.type === 'keydown') {
48619             return (lastMouse && lastMouse.target.__data__) || {};
48620         } else {
48621             return event.target.__data__ || {};
48622         }
48623     }
48624
48625
48626     function mousedown() {
48627
48628         function point() {
48629             var p = context.container().node();
48630             return touchId !== null ? touches(p).filter(function(p) {
48631                 return p.identifier === touchId;
48632             })[0] : mouse(p);
48633         }
48634
48635         var element = select(this),
48636             touchId = event.touches ? event.changedTouches[0].identifier : null,
48637             t1 = +new Date(),
48638             p1 = point();
48639
48640         element.on('mousemove.draw', null);
48641
48642         select(window).on('mouseup.draw', function() {
48643             var t2 = +new Date(),
48644                 p2 = point(),
48645                 dist = geoEuclideanDistance(p1, p2);
48646
48647             element.on('mousemove.draw', mousemove);
48648             select(window).on('mouseup.draw', null);
48649
48650             if (dist < closeTolerance || (dist < tolerance && (t2 - t1) < 500)) {
48651                 // Prevent a quick second click
48652                 select(window).on('click.draw-block', function() {
48653                     event.stopPropagation();
48654                 }, true);
48655
48656                 context.map().dblclickEnable(false);
48657
48658                 window.setTimeout(function() {
48659                     context.map().dblclickEnable(true);
48660                     select(window).on('click.draw-block', null);
48661                 }, 500);
48662
48663                 click();
48664             }
48665         }, true);
48666     }
48667
48668
48669     function mousemove() {
48670         lastMouse = event;
48671         dispatch$$1.call('move', this, datum());
48672     }
48673
48674
48675     function mouseenter() {
48676         mouseLeave = false;
48677     }
48678
48679
48680     function mouseleave() {
48681         mouseLeave = true;
48682     }
48683
48684
48685     function click() {
48686         var d = datum();
48687         if (d.type === 'way') {
48688             var dims = context.map().dimensions(),
48689                 mouse$$1 = context.mouse(),
48690                 pad = 5,
48691                 trySnap = mouse$$1[0] > pad && mouse$$1[0] < dims[0] - pad &&
48692                     mouse$$1[1] > pad && mouse$$1[1] < dims[1] - pad;
48693
48694             if (trySnap) {
48695                 var choice = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection),
48696                     edge = [d.nodes[choice.index - 1], d.nodes[choice.index]];
48697                 dispatch$$1.call('clickWay', this, choice.loc, edge);
48698             } else {
48699                 dispatch$$1.call('click', this, context.map().mouseCoordinates());
48700             }
48701
48702         } else if (d.type === 'node') {
48703             dispatch$$1.call('clickNode', this, d);
48704
48705         } else {
48706             dispatch$$1.call('click', this, context.map().mouseCoordinates());
48707         }
48708     }
48709
48710
48711     function space() {
48712         var currSpace = context.mouse();
48713         if (cached.disableSpace && cached.lastSpace) {
48714             var dist = geoEuclideanDistance(cached.lastSpace, currSpace);
48715             if (dist > tolerance) {
48716                 cached.disableSpace = false;
48717             }
48718         }
48719
48720         if (cached.disableSpace || mouseLeave || !lastMouse) return;
48721
48722         // user must move mouse or release space bar to allow another click
48723         cached.lastSpace = currSpace;
48724         cached.disableSpace = true;
48725
48726         select(window).on('keyup.space-block', function() {
48727             cached.disableSpace = false;
48728             select(window).on('keyup.space-block', null);
48729         });
48730
48731         event.preventDefault();
48732         click();
48733     }
48734
48735
48736     function backspace() {
48737         event.preventDefault();
48738         dispatch$$1.call('undo');
48739     }
48740
48741
48742     function del() {
48743         event.preventDefault();
48744         dispatch$$1.call('cancel');
48745     }
48746
48747
48748     function ret() {
48749         event.preventDefault();
48750         dispatch$$1.call('finish');
48751     }
48752
48753
48754     function draw(selection$$1) {
48755         context.install(hover);
48756         context.install(edit);
48757
48758         if (!context.inIntro() && !cached.usedTails[tail.text()]) {
48759             context.install(tail);
48760         }
48761
48762         keybinding
48763             .on('⌫', backspace)
48764             .on('⌦', del)
48765             .on('⎋', ret)
48766             .on('↩', ret)
48767             .on('space', space)
48768             .on('⌥space', space);
48769
48770         selection$$1
48771             .on('mouseenter.draw', mouseenter)
48772             .on('mouseleave.draw', mouseleave)
48773             .on('mousedown.draw', mousedown)
48774             .on('mousemove.draw', mousemove);
48775
48776         select(document)
48777             .call(keybinding);
48778
48779         return draw;
48780     }
48781
48782
48783     draw.off = function(selection$$1) {
48784         context.ui().sidebar.hover.cancel();
48785         context.uninstall(hover);
48786         context.uninstall(edit);
48787
48788         if (!context.inIntro() && !cached.usedTails[tail.text()]) {
48789             context.uninstall(tail);
48790             cached.usedTails[tail.text()] = true;
48791         }
48792
48793         selection$$1
48794             .on('mouseenter.draw', null)
48795             .on('mouseleave.draw', null)
48796             .on('mousedown.draw', null)
48797             .on('mousemove.draw', null);
48798
48799         select(window)
48800             .on('mouseup.draw', null);
48801             // note: keyup.space-block, click.draw-block should remain
48802
48803         select(document)
48804             .call(keybinding.off);
48805     };
48806
48807
48808     draw.tail = function(_) {
48809         tail.text(_);
48810         return draw;
48811     };
48812
48813
48814     return utilRebind(draw, dispatch$$1, 'on');
48815 }
48816
48817 function behaviorAddWay(context) {
48818     var dispatch$$1 = dispatch('start', 'startFromWay', 'startFromNode'),
48819         draw = behaviorDraw(context);
48820
48821     var addWay = function(surface) {
48822         draw.on('click', function() { dispatch$$1.apply('start', this, arguments); })
48823             .on('clickWay', function() { dispatch$$1.apply('startFromWay', this, arguments); })
48824             .on('clickNode', function() { dispatch$$1.apply('startFromNode', this, arguments); })
48825             .on('cancel', addWay.cancel)
48826             .on('finish', addWay.cancel);
48827
48828         context.map()
48829             .dblclickEnable(false);
48830
48831         surface.call(draw);
48832     };
48833
48834
48835     addWay.off = function(surface) {
48836         surface.call(draw.off);
48837     };
48838
48839
48840     addWay.cancel = function() {
48841         window.setTimeout(function() {
48842             context.map().dblclickEnable(true);
48843         }, 1000);
48844
48845         context.enter(modeBrowse$$1(context));
48846     };
48847
48848
48849     addWay.tail = function(text$$1) {
48850         draw.tail(text$$1);
48851         return addWay;
48852     };
48853
48854
48855     return utilRebind(addWay, dispatch$$1, 'on');
48856 }
48857
48858 function behaviorBreathe() {
48859     var duration = 800,
48860         steps = 4,
48861         selector$$1 = '.selected.shadow, .selected .shadow',
48862         selected = select(null),
48863         classed = '',
48864         params = {},
48865         done = false,
48866         timer$$1;
48867
48868
48869     // This is a workaround for a bug in rollup v0.36
48870     // https://github.com/rollup/rollup/issues/984
48871     // The symbol for this default export is not used anywhere, but it
48872     // needs to be called in order to be included in the bundle.
48873     var t = transition();
48874
48875
48876     function ratchetyInterpolator(a, b, steps, units) {
48877         a = parseFloat(a);
48878         b = parseFloat(b);
48879         var sample = quantize$1()
48880             .domain([0, 1])
48881             .range(quantize(interpolateNumber(a, b), steps));
48882
48883         return function(t) {
48884             return String(sample(t)) + (units || '');
48885         };
48886     }
48887
48888
48889     function reset(selection$$1) {
48890         selection$$1
48891             .style('stroke-opacity', null)
48892             .style('stroke-width', null)
48893             .style('fill-opacity', null)
48894             .style('r', null);
48895     }
48896
48897
48898     function setAnimationParams(transition$$1, fromTo) {
48899         var toFrom = (fromTo === 'from' ? 'to' : 'from');
48900
48901         transition$$1
48902             .styleTween('stroke-opacity', function(d) {
48903                 return ratchetyInterpolator(
48904                     params[d.id][toFrom].opacity,
48905                     params[d.id][fromTo].opacity,
48906                     steps
48907                 );
48908             })
48909             .styleTween('stroke-width', function(d) {
48910                 return ratchetyInterpolator(
48911                     params[d.id][toFrom].width,
48912                     params[d.id][fromTo].width,
48913                     steps,
48914                     'px'
48915                 );
48916             })
48917             .styleTween('fill-opacity', function(d) {
48918                 return ratchetyInterpolator(
48919                     params[d.id][toFrom].opacity,
48920                     params[d.id][fromTo].opacity,
48921                     steps
48922                 );
48923             })
48924             .styleTween('r', function(d) {
48925                 return ratchetyInterpolator(
48926                     params[d.id][toFrom].width,
48927                     params[d.id][fromTo].width,
48928                     steps,
48929                     'px'
48930                 );
48931             });
48932     }
48933
48934
48935     function calcAnimationParams(selection$$1) {
48936         selection$$1
48937             .call(reset)
48938             .each(function(d) {
48939                 var s = select(this),
48940                     tag = s.node().tagName,
48941                     p = {'from': {}, 'to': {}},
48942                     opacity, width;
48943
48944                 // determine base opacity and width
48945                 if (tag === 'circle') {
48946                     opacity = parseFloat(s.style('fill-opacity') || 0.5);
48947                     width = parseFloat(s.style('r') || 15.5);
48948                 } else {
48949                     opacity = parseFloat(s.style('stroke-opacity') || 0.7);
48950                     width = parseFloat(s.style('stroke-width') || 10);
48951                 }
48952
48953                 // calculate from/to interpolation params..
48954                 p.tag = tag;
48955                 p.from.opacity = opacity * 0.6;
48956                 p.to.opacity = opacity * 1.25;
48957                 p.from.width = width * 0.9;
48958                 p.to.width = width * (tag === 'circle' ? 1.5 : 1.25);
48959                 params[d.id] = p;
48960             });
48961     }
48962
48963
48964     function run(surface, fromTo) {
48965         var toFrom = (fromTo === 'from' ? 'to' : 'from'),
48966             currSelected = surface.selectAll(selector$$1),
48967             currClassed = surface.attr('class');
48968
48969         if (done || currSelected.empty()) {
48970             selected.call(reset);
48971             return;
48972         }
48973
48974         if (!lodash.isEqual(currSelected.data(), selected.data()) || currClassed !== classed) {
48975             selected.call(reset);
48976             classed = currClassed;
48977             selected = currSelected.call(calcAnimationParams);
48978         }
48979
48980         selected
48981             .transition()
48982             .duration(duration)
48983             .call(setAnimationParams, fromTo)
48984             .on('end', function() {
48985                 surface.call(run, toFrom);
48986             });
48987     }
48988
48989
48990     var breathe = function(surface) {
48991         done = false;
48992         timer$$1 = timer(function() {
48993             // wait for elements to actually become selected
48994             if (surface.selectAll(selector$$1).empty()) {
48995                 return false;
48996             }
48997
48998             surface.call(run, 'from');
48999             timer$$1.stop();
49000             return true;
49001         }, 20);
49002     };
49003
49004
49005     breathe.off = function() {
49006         done = true;
49007         timer$$1.stop();
49008         selected
49009             .interrupt()
49010             .call(reset);
49011     };
49012
49013
49014     return breathe;
49015 }
49016
49017 function behaviorCopy(context) {
49018     var keybinding = d3keybinding('copy');
49019
49020
49021     function groupEntities(ids, graph) {
49022         var entities = ids.map(function (id) { return graph.entity(id); });
49023         return lodash.extend({relation: [], way: [], node: []},
49024             lodash.groupBy(entities, function(entity) { return entity.type; }));
49025     }
49026
49027
49028     function getDescendants(id, graph, descendants) {
49029         var entity = graph.entity(id),
49030             i, children;
49031
49032         descendants = descendants || {};
49033
49034         if (entity.type === 'relation') {
49035             children = lodash.map(entity.members, 'id');
49036         } else if (entity.type === 'way') {
49037             children = entity.nodes;
49038         } else {
49039             children = [];
49040         }
49041
49042         for (i = 0; i < children.length; i++) {
49043             if (!descendants[children[i]]) {
49044                 descendants[children[i]] = true;
49045                 descendants = getDescendants(children[i], graph, descendants);
49046             }
49047         }
49048
49049         return descendants;
49050     }
49051
49052
49053     function doCopy() {
49054         event.preventDefault();
49055         if (context.inIntro()) return;
49056
49057         var graph = context.graph(),
49058             selected = groupEntities(context.selectedIDs(), graph),
49059             canCopy = [],
49060             skip = {},
49061             i, entity;
49062
49063         for (i = 0; i < selected.relation.length; i++) {
49064             entity = selected.relation[i];
49065             if (!skip[entity.id] && entity.isComplete(graph)) {
49066                 canCopy.push(entity.id);
49067                 skip = getDescendants(entity.id, graph, skip);
49068             }
49069         }
49070         for (i = 0; i < selected.way.length; i++) {
49071             entity = selected.way[i];
49072             if (!skip[entity.id]) {
49073                 canCopy.push(entity.id);
49074                 skip = getDescendants(entity.id, graph, skip);
49075             }
49076         }
49077         for (i = 0; i < selected.node.length; i++) {
49078             entity = selected.node[i];
49079             if (!skip[entity.id]) {
49080                 canCopy.push(entity.id);
49081             }
49082         }
49083
49084         context.copyIDs(canCopy);
49085     }
49086
49087
49088     function copy() {
49089         keybinding.on(uiCmd('⌘C'), doCopy);
49090         select(document).call(keybinding);
49091         return copy;
49092     }
49093
49094
49095     copy.off = function() {
49096         select(document).call(keybinding.off);
49097     };
49098
49099
49100     return copy;
49101 }
49102
49103 /*
49104     `behaviorDrag` is like `d3.behavior.drag`, with the following differences:
49105
49106     * The `origin` function is expected to return an [x, y] tuple rather than an
49107       {x, y} object.
49108     * The events are `start`, `move`, and `end`.
49109       (https://github.com/mbostock/d3/issues/563)
49110     * The `start` event is not dispatched until the first cursor movement occurs.
49111       (https://github.com/mbostock/d3/pull/368)
49112     * The `move` event has a `point` and `delta` [x, y] tuple properties rather
49113       than `x`, `y`, `dx`, and `dy` properties.
49114     * The `end` event is not dispatched if no movement occurs.
49115     * An `off` function is available that unbinds the drag's internal event handlers.
49116     * Delegation is supported via the `delegate` function.
49117
49118  */
49119 function behaviorDrag() {
49120     var event$$1 = dispatch('start', 'move', 'end'),
49121         origin = null,
49122         selector$$1 = '',
49123         filter = null,
49124         event_, target, surface;
49125
49126
49127     function d3_eventCancel() {
49128         event.stopPropagation();
49129         event.preventDefault();
49130     }
49131
49132     function eventOf(thiz, argumentz) {
49133         return function(e1) {
49134             e1.target = drag$$1;
49135             customEvent(e1, event$$1.apply, event$$1, [e1.type, thiz, argumentz]);
49136         };
49137     }
49138
49139     var d3_event_userSelectProperty = utilPrefixCSSProperty('UserSelect'),
49140         d3_event_userSelectSuppress = d3_event_userSelectProperty ?
49141             function () {
49142                 var selection$$1 = selection(),
49143                     select$$1 = selection$$1.style(d3_event_userSelectProperty);
49144                 selection$$1.style(d3_event_userSelectProperty, 'none');
49145                 return function () {
49146                     selection$$1.style(d3_event_userSelectProperty, select$$1);
49147                 };
49148             } :
49149             function (type) {
49150                 var w = select(window).on('selectstart.' + type, d3_eventCancel);
49151                 return function () {
49152                     w.on('selectstart.' + type, null);
49153                 };
49154             };
49155
49156
49157     function mousedown() {
49158         target = this;
49159         event_ = eventOf(target, arguments);
49160
49161         var eventTarget = event.target,
49162             touchId = event.touches ? event.changedTouches[0].identifier : null,
49163             offset,
49164             origin_ = point(),
49165             started = false,
49166             selectEnable = d3_event_userSelectSuppress(touchId !== null ? 'drag-' + touchId : 'drag');
49167
49168         var w = select(window)
49169             .on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', dragmove)
49170             .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', dragend, true);
49171
49172         if (origin) {
49173             offset = origin.apply(target, arguments);
49174             offset = [offset[0] - origin_[0], offset[1] - origin_[1]];
49175         } else {
49176             offset = [0, 0];
49177         }
49178
49179         if (touchId === null) event.stopPropagation();
49180
49181         function point() {
49182             var p = target.parentNode || surface;
49183             return touchId !== null ? touches(p).filter(function(p) {
49184                 return p.identifier === touchId;
49185             })[0] : mouse(p);
49186         }
49187
49188
49189         function dragmove() {
49190             var p = point(),
49191                 dx = p[0] - origin_[0],
49192                 dy = p[1] - origin_[1];
49193
49194             if (dx === 0 && dy === 0)
49195                 return;
49196
49197             if (!started) {
49198                 started = true;
49199                 event_({
49200                     type: 'start'
49201                 });
49202             }
49203
49204             origin_ = p;
49205             d3_eventCancel();
49206
49207             event_({
49208                 type: 'move',
49209                 point: [p[0] + offset[0],  p[1] + offset[1]],
49210                 delta: [dx, dy]
49211             });
49212         }
49213
49214
49215         function dragend() {
49216             if (started) {
49217                 event_({
49218                     type: 'end'
49219                 });
49220
49221                 d3_eventCancel();
49222                 if (event.target === eventTarget) w.on('click.drag', click, true);
49223             }
49224
49225             w.on(touchId !== null ? 'touchmove.drag-' + touchId : 'mousemove.drag', null)
49226                 .on(touchId !== null ? 'touchend.drag-' + touchId : 'mouseup.drag', null);
49227             selectEnable();
49228         }
49229
49230
49231         function click() {
49232             d3_eventCancel();
49233             w.on('click.drag', null);
49234         }
49235     }
49236
49237
49238     function drag$$1(selection$$1) {
49239         var matchesSelector = utilPrefixDOMProperty('matchesSelector'),
49240             delegate = mousedown;
49241
49242         if (selector$$1) {
49243             delegate = function() {
49244                 var root = this,
49245                     target = event.target;
49246                 for (; target && target !== root; target = target.parentNode) {
49247                     if (target[matchesSelector](selector$$1) &&
49248                             (!filter || filter(target.__data__))) {
49249                         return mousedown.call(target, target.__data__);
49250                     }
49251                 }
49252             };
49253         }
49254
49255         selection$$1.on('mousedown.drag' + selector$$1, delegate)
49256             .on('touchstart.drag' + selector$$1, delegate);
49257     }
49258
49259
49260     drag$$1.off = function(selection$$1) {
49261         selection$$1.on('mousedown.drag' + selector$$1, null)
49262             .on('touchstart.drag' + selector$$1, null);
49263     };
49264
49265
49266     drag$$1.delegate = function(_) {
49267         if (!arguments.length) return selector$$1;
49268         selector$$1 = _;
49269         return drag$$1;
49270     };
49271
49272
49273     drag$$1.filter = function(_) {
49274         if (!arguments.length) return origin;
49275         filter = _;
49276         return drag$$1;
49277     };
49278
49279
49280     drag$$1.origin = function (_) {
49281         if (!arguments.length) return origin;
49282         origin = _;
49283         return drag$$1;
49284     };
49285
49286
49287     drag$$1.cancel = function() {
49288         select(window)
49289             .on('mousemove.drag', null)
49290             .on('mouseup.drag', null);
49291         return drag$$1;
49292     };
49293
49294
49295     drag$$1.target = function() {
49296         if (!arguments.length) return target;
49297         target = arguments[0];
49298         event_ = eventOf(target, Array.prototype.slice.call(arguments, 1));
49299         return drag$$1;
49300     };
49301
49302
49303     drag$$1.surface = function() {
49304         if (!arguments.length) return surface;
49305         surface = arguments[0];
49306         return drag$$1;
49307     };
49308
49309
49310     return utilRebind(drag$$1, event$$1, 'on');
49311 }
49312
49313 function behaviorDrawWay(context, wayId, index, mode, baseGraph) {
49314
49315     var way = context.entity(wayId),
49316         isArea = context.geometry(wayId) === 'area',
49317         finished = false,
49318         annotation = t((way.isDegenerate() ?
49319             'operations.start.annotation.' :
49320             'operations.continue.annotation.') + context.geometry(wayId)),
49321         draw = behaviorDraw(context);
49322
49323     var startIndex = typeof index === 'undefined' ? way.nodes.length - 1 : 0,
49324         start = osmNode({loc: context.graph().entity(way.nodes[startIndex]).loc}),
49325         end = osmNode({loc: context.map().mouseCoordinates()}),
49326         segment = osmWay({
49327             nodes: typeof index === 'undefined' ? [start.id, end.id] : [end.id, start.id],
49328             tags: lodash.clone(way.tags)
49329         });
49330
49331     var fn = context[way.isDegenerate() ? 'replace' : 'perform'];
49332     if (isArea) {
49333         fn(actionAddEntity(end),
49334             actionAddVertex(wayId, end.id, index)
49335         );
49336     } else {
49337         fn(actionAddEntity(start),
49338             actionAddEntity(end),
49339             actionAddEntity(segment)
49340         );
49341     }
49342
49343
49344     function move(datum) {
49345         var loc;
49346
49347         if (datum.type === 'node' && datum.id !== end.id) {
49348             loc = datum.loc;
49349
49350         } else if (datum.type === 'way' && datum.id !== segment.id) {
49351             var dims = context.map().dimensions(),
49352                 mouse = context.mouse(),
49353                 pad = 5,
49354                 trySnap = mouse[0] > pad && mouse[0] < dims[0] - pad &&
49355                     mouse[1] > pad && mouse[1] < dims[1] - pad;
49356
49357             if (trySnap) {
49358                 loc = geoChooseEdge(context.childNodes(datum), context.mouse(), context.projection).loc;
49359             }
49360         }
49361
49362         if (!loc) {
49363             loc = context.map().mouseCoordinates();
49364         }
49365
49366         context.replace(actionMoveNode(end.id, loc));
49367     }
49368
49369
49370     function undone() {
49371         finished = true;
49372         context.enter(modeBrowse$$1(context));
49373     }
49374
49375
49376     function setActiveElements() {
49377         var active = isArea ? [wayId, end.id] : [segment.id, start.id, end.id];
49378         context.surface().selectAll(utilEntitySelector(active))
49379             .classed('active', true);
49380     }
49381
49382
49383     var drawWay = function(surface) {
49384         draw.on('move', move)
49385             .on('click', drawWay.add)
49386             .on('clickWay', drawWay.addWay)
49387             .on('clickNode', drawWay.addNode)
49388             .on('undo', context.undo)
49389             .on('cancel', drawWay.cancel)
49390             .on('finish', drawWay.finish);
49391
49392         context.map()
49393             .dblclickEnable(false)
49394             .on('drawn.draw', setActiveElements);
49395
49396         setActiveElements();
49397
49398         surface.call(draw);
49399
49400         context.history()
49401             .on('undone.draw', undone);
49402     };
49403
49404
49405     drawWay.off = function(surface) {
49406         if (!finished)
49407             context.pop();
49408
49409         context.map()
49410             .on('drawn.draw', null);
49411
49412         surface.call(draw.off)
49413             .selectAll('.active')
49414             .classed('active', false);
49415
49416         context.history()
49417             .on('undone.draw', null);
49418     };
49419
49420
49421     function ReplaceTemporaryNode(newNode) {
49422         return function(graph) {
49423             if (isArea) {
49424                 return graph
49425                     .replace(way.addNode(newNode.id, index))
49426                     .remove(end);
49427
49428             } else {
49429                 return graph
49430                     .replace(graph.entity(wayId).addNode(newNode.id, index))
49431                     .remove(end)
49432                     .remove(segment)
49433                     .remove(start);
49434             }
49435         };
49436     }
49437
49438
49439     // Accept the current position of the temporary node and continue drawing.
49440     drawWay.add = function(loc) {
49441         // prevent duplicate nodes
49442         var last = context.hasEntity(way.nodes[way.nodes.length - (isArea ? 2 : 1)]);
49443         if (last && last.loc[0] === loc[0] && last.loc[1] === loc[1]) return;
49444
49445         var newNode = osmNode({loc: loc});
49446
49447         context.replace(
49448             actionAddEntity(newNode),
49449             ReplaceTemporaryNode(newNode),
49450             annotation
49451         );
49452
49453         finished = true;
49454         context.enter(mode);
49455     };
49456
49457
49458     // Connect the way to an existing way.
49459     drawWay.addWay = function(loc, edge) {
49460         var previousEdge = startIndex ?
49461             [way.nodes[startIndex], way.nodes[startIndex - 1]] :
49462             [way.nodes[0], way.nodes[1]];
49463
49464         // Avoid creating duplicate segments
49465         if (!isArea && geoEdgeEqual(edge, previousEdge))
49466             return;
49467
49468         var newNode = osmNode({ loc: loc });
49469
49470         context.perform(
49471             actionAddMidpoint({ loc: loc, edge: edge}, newNode),
49472             ReplaceTemporaryNode(newNode),
49473             annotation
49474         );
49475
49476         finished = true;
49477         context.enter(mode);
49478     };
49479
49480
49481     // Connect the way to an existing node and continue drawing.
49482     drawWay.addNode = function(node) {
49483         // Avoid creating duplicate segments
49484         if (way.areAdjacent(node.id, way.nodes[way.nodes.length - 1])) return;
49485
49486         context.perform(
49487             ReplaceTemporaryNode(node),
49488             annotation
49489         );
49490
49491         finished = true;
49492         context.enter(mode);
49493     };
49494
49495
49496     // Finish the draw operation, removing the temporary node. If the way has enough
49497     // nodes to be valid, it's selected. Otherwise, return to browse mode.
49498     drawWay.finish = function() {
49499         context.pop();
49500         finished = true;
49501
49502         window.setTimeout(function() {
49503             context.map().dblclickEnable(true);
49504         }, 1000);
49505
49506         if (context.hasEntity(wayId)) {
49507             context.enter(
49508                 modeSelect(context, [wayId]).suppressMenu(true).newFeature(true)
49509             );
49510         } else {
49511             context.enter(modeBrowse$$1(context));
49512         }
49513     };
49514
49515
49516     // Cancel the draw operation and return to browse, deleting everything drawn.
49517     drawWay.cancel = function() {
49518         context.perform(
49519             utilFunctor(baseGraph),
49520             t('operations.cancel_draw.annotation'));
49521
49522         window.setTimeout(function() {
49523             context.map().dblclickEnable(true);
49524         }, 1000);
49525
49526         finished = true;
49527         context.enter(modeBrowse$$1(context));
49528     };
49529
49530
49531     drawWay.tail = function(text) {
49532         draw.tail(text);
49533         return drawWay;
49534     };
49535
49536
49537     return drawWay;
49538 }
49539
49540 function behaviorHash(context) {
49541     var s0 = null, // cached window.location.hash
49542         lat = 90 - 1e-8; // allowable latitude range
49543
49544
49545     var parser = function(map$$1, s) {
49546         var q = utilStringQs(s);
49547         var args = (q.map || '').split('/').map(Number);
49548         if (args.length < 3 || args.some(isNaN)) {
49549             return true; // replace bogus hash
49550         } else if (s !== formatter(map$$1).slice(1)) {
49551             map$$1.centerZoom([args[2],
49552                 Math.min(lat, Math.max(-lat, args[1]))], args[0]);
49553         }
49554     };
49555
49556
49557     var formatter = function(map$$1) {
49558         var mode = context.mode(),
49559             center = map$$1.center(),
49560             zoom$$1 = map$$1.zoom(),
49561             precision = Math.max(0, Math.ceil(Math.log(zoom$$1) / Math.LN2)),
49562             q = lodash.omit(utilStringQs(window.location.hash.substring(1)), 'comment'),
49563             newParams = {};
49564
49565         if (mode && mode.id === 'browse') {
49566             delete q.id;
49567         } else {
49568             var selected = context.selectedIDs().filter(function(id) {
49569                 return !context.entity(id).isNew();
49570             });
49571             if (selected.length) {
49572                 newParams.id = selected.join(',');
49573             }
49574         }
49575
49576         newParams.map = zoom$$1.toFixed(2) +
49577                 '/' + center[1].toFixed(precision) +
49578                 '/' + center[0].toFixed(precision);
49579
49580         return '#' + utilQsString(lodash.assign(q, newParams), true);
49581     };
49582
49583
49584     function update() {
49585         if (context.inIntro()) return;
49586         var s1 = formatter(context.map());
49587         if (s0 !== s1) {
49588             window.location.replace(s0 = s1);  // don't recenter the map!
49589         }
49590     }
49591
49592
49593     var throttledUpdate = lodash.throttle(update, 500);
49594
49595
49596     function hashchange() {
49597         if (window.location.hash === s0) return;  // ignore spurious hashchange events
49598         if (parser(context.map(), (s0 = window.location.hash).substring(1))) {
49599             update(); // replace bogus hash
49600         }
49601     }
49602
49603
49604     function hash() {
49605         context.map()
49606             .on('move.hash', throttledUpdate);
49607
49608         context
49609             .on('enter.hash', throttledUpdate);
49610
49611         select(window)
49612             .on('hashchange.hash', hashchange);
49613
49614         if (window.location.hash) {
49615             var q = utilStringQs(window.location.hash.substring(1));
49616             if (q.id) context.zoomToEntity(q.id.split(',')[0], !q.map);
49617             if (q.comment) context.storage('comment', q.comment);
49618             hashchange();
49619             if (q.map) hash.hadHash = true;
49620         }
49621     }
49622
49623
49624     hash.off = function() {
49625         throttledUpdate.cancel();
49626
49627         context.map()
49628             .on('move.hash', null);
49629
49630         context
49631             .on('enter.hash', null);
49632
49633         select(window)
49634             .on('hashchange.hash', null);
49635
49636         window.location.hash = '';
49637     };
49638
49639
49640     return hash;
49641 }
49642
49643 function behaviorLasso(context) {
49644
49645     var behavior = function(selection$$1) {
49646         var lasso;
49647
49648
49649         function mousedown() {
49650             var button = 0;  // left
49651             if (event.button === button && event.shiftKey === true) {
49652                 lasso = null;
49653
49654                 selection$$1
49655                     .on('mousemove.lasso', mousemove)
49656                     .on('mouseup.lasso', mouseup);
49657
49658                 event.stopPropagation();
49659             }
49660         }
49661
49662
49663         function mousemove() {
49664             if (!lasso) {
49665                 lasso = uiLasso(context);
49666                 context.surface().call(lasso);
49667             }
49668
49669             lasso.p(context.mouse());
49670         }
49671
49672
49673         function normalize(a, b) {
49674             return [
49675                 [Math.min(a[0], b[0]), Math.min(a[1], b[1])],
49676                 [Math.max(a[0], b[0]), Math.max(a[1], b[1])]];
49677         }
49678
49679
49680         function lassoed() {
49681             if (!lasso) return [];
49682
49683             var graph = context.graph(),
49684                 bounds = lasso.extent().map(context.projection.invert),
49685                 extent$$1 = geoExtent$$1(normalize(bounds[0], bounds[1]));
49686
49687             return lodash.map(context.intersects(extent$$1).filter(function(entity) {
49688                 return entity.type === 'node' &&
49689                     geoPointInPolygon(context.projection(entity.loc), lasso.coordinates) &&
49690                     !context.features().isHidden(entity, graph, entity.geometry(graph));
49691             }), 'id');
49692         }
49693
49694
49695         function mouseup() {
49696             selection$$1
49697                 .on('mousemove.lasso', null)
49698                 .on('mouseup.lasso', null);
49699
49700             if (!lasso) return;
49701
49702             var ids = lassoed();
49703             lasso.close();
49704
49705             if (ids.length) {
49706                 context.enter(modeSelect(context, ids));
49707             }
49708         }
49709
49710         selection$$1
49711             .on('mousedown.lasso', mousedown);
49712     };
49713
49714
49715     behavior.off = function(selection$$1) {
49716         selection$$1.on('mousedown.lasso', null);
49717     };
49718
49719
49720     return behavior;
49721 }
49722
49723 function behaviorPaste(context) {
49724     var keybinding = d3keybinding('paste');
49725
49726     function omitTag(v, k) {
49727         return (
49728             k === 'phone' ||
49729             k === 'fax' ||
49730             k === 'email' ||
49731             k === 'website' ||
49732             k === 'url' ||
49733             k === 'note' ||
49734             k === 'description' ||
49735             k.indexOf('name') !== -1 ||
49736             k.indexOf('wiki') === 0 ||
49737             k.indexOf('addr:') === 0 ||
49738             k.indexOf('contact:') === 0
49739         );
49740     }
49741
49742
49743     function doPaste() {
49744         event.preventDefault();
49745         if (context.inIntro()) return;
49746
49747         var baseGraph = context.graph(),
49748             mouse$$1 = context.mouse(),
49749             projection = context.projection,
49750             viewport = geoExtent$$1(projection.clipExtent()).polygon();
49751
49752         if (!geoPointInPolygon(mouse$$1, viewport)) return;
49753
49754         var extent$$1 = geoExtent$$1(),
49755             oldIDs = context.copyIDs(),
49756             oldGraph = context.copyGraph(),
49757             newIDs = [];
49758
49759         if (!oldIDs.length) return;
49760
49761         var action = actionCopyEntities(oldIDs, oldGraph);
49762         context.perform(action);
49763
49764         var copies = action.copies();
49765         for (var id in copies) {
49766             var oldEntity = oldGraph.entity(id),
49767                 newEntity = copies[id];
49768
49769             extent$$1._extend(oldEntity.extent(oldGraph));
49770             newIDs.push(newEntity.id);
49771             context.perform(
49772                 actionChangeTags(newEntity.id, lodash.omit(newEntity.tags, omitTag))
49773             );
49774         }
49775
49776         // Put pasted objects where mouse pointer is..
49777         var center = projection(extent$$1.center()),
49778             delta = [ mouse$$1[0] - center[0], mouse$$1[1] - center[1] ];
49779
49780         context.perform(actionMove(newIDs, delta, projection));
49781         context.enter(modeMove$$1(context, newIDs, baseGraph));
49782     }
49783
49784
49785     function paste() {
49786         keybinding.on(uiCmd('⌘V'), doPaste);
49787         select(document).call(keybinding);
49788         return paste;
49789     }
49790
49791
49792     paste.off = function() {
49793         select(document).call(keybinding.off);
49794     };
49795
49796
49797     return paste;
49798 }
49799
49800 function behaviorSelect(context) {
49801
49802     function keydown() {
49803         if (event && event.shiftKey) {
49804             context.surface()
49805                 .classed('behavior-multiselect', true);
49806         }
49807     }
49808
49809
49810     function keyup() {
49811         if (!event || !event.shiftKey) {
49812             context.surface()
49813                 .classed('behavior-multiselect', false);
49814         }
49815     }
49816
49817
49818     function click() {
49819         var datum = event.target.__data__,
49820             lasso = select('#surface .lasso').node(),
49821             mode = context.mode();
49822
49823         if (!(datum instanceof osmEntity$$1)) {
49824             if (!event.shiftKey && !lasso && mode.id !== 'browse')
49825                 context.enter(modeBrowse$$1(context));
49826
49827         } else if (!event.shiftKey && !lasso) {
49828             // Avoid re-entering Select mode with same entity.
49829             if (context.selectedIDs().length !== 1 || context.selectedIDs()[0] !== datum.id) {
49830                 context.enter(modeSelect(context, [datum.id]));
49831             } else {
49832                 mode.suppressMenu(false).reselect();
49833             }
49834         } else if (context.selectedIDs().indexOf(datum.id) >= 0) {
49835             var selectedIDs = lodash.without(context.selectedIDs(), datum.id);
49836             context.enter(selectedIDs.length ? modeSelect(context, selectedIDs) : modeBrowse$$1(context));
49837
49838         } else {
49839             context.enter(modeSelect(context, context.selectedIDs().concat([datum.id])));
49840         }
49841     }
49842
49843
49844     var behavior = function(selection$$1) {
49845         select(window)
49846             .on('keydown.select', keydown)
49847             .on('keyup.select', keyup);
49848
49849         selection$$1.on('click.select', click);
49850
49851         keydown();
49852     };
49853
49854
49855     behavior.off = function(selection$$1) {
49856         select(window)
49857             .on('keydown.select', null)
49858             .on('keyup.select', null);
49859
49860         selection$$1.on('click.select', null);
49861
49862         keyup();
49863     };
49864
49865
49866     return behavior;
49867 }
49868
49869 function modeAddArea$$1(context) {
49870     var mode = {
49871         id: 'add-area',
49872         button: 'area',
49873         title: t('modes.add_area.title'),
49874         description: t('modes.add_area.description'),
49875         key: '3'
49876     };
49877
49878     var behavior = behaviorAddWay(context)
49879             .tail(t('modes.add_area.tail'))
49880             .on('start', start)
49881             .on('startFromWay', startFromWay)
49882             .on('startFromNode', startFromNode),
49883         defaultTags = { area: 'yes' };
49884
49885
49886     function start(loc) {
49887         var graph = context.graph(),
49888             node = osmNode({ loc: loc }),
49889             way = osmWay({ tags: defaultTags });
49890
49891         context.perform(
49892             actionAddEntity(node),
49893             actionAddEntity(way),
49894             actionAddVertex(way.id, node.id),
49895             actionAddVertex(way.id, node.id)
49896         );
49897
49898         context.enter(modeDrawArea(context, way.id, graph));
49899     }
49900
49901
49902     function startFromWay(loc, edge) {
49903         var graph = context.graph(),
49904             node = osmNode({ loc: loc }),
49905             way = osmWay({ tags: defaultTags });
49906
49907         context.perform(
49908             actionAddEntity(node),
49909             actionAddEntity(way),
49910             actionAddVertex(way.id, node.id),
49911             actionAddVertex(way.id, node.id),
49912             actionAddMidpoint({ loc: loc, edge: edge }, node)
49913         );
49914
49915         context.enter(modeDrawArea(context, way.id, graph));
49916     }
49917
49918
49919     function startFromNode(node) {
49920         var graph = context.graph(),
49921             way = osmWay({ tags: defaultTags });
49922
49923         context.perform(
49924             actionAddEntity(way),
49925             actionAddVertex(way.id, node.id),
49926             actionAddVertex(way.id, node.id)
49927         );
49928
49929         context.enter(modeDrawArea(context, way.id, graph));
49930     }
49931
49932
49933     mode.enter = function() {
49934         context.install(behavior);
49935     };
49936
49937
49938     mode.exit = function() {
49939         context.uninstall(behavior);
49940     };
49941
49942
49943     return mode;
49944 }
49945
49946 function modeAddLine$$1(context) {
49947     var mode = {
49948         id: 'add-line',
49949         button: 'line',
49950         title: t('modes.add_line.title'),
49951         description: t('modes.add_line.description'),
49952         key: '2'
49953     };
49954
49955     var behavior = behaviorAddWay(context)
49956         .tail(t('modes.add_line.tail'))
49957         .on('start', start)
49958         .on('startFromWay', startFromWay)
49959         .on('startFromNode', startFromNode);
49960
49961
49962     function start(loc) {
49963         var baseGraph = context.graph(),
49964             node = osmNode({ loc: loc }),
49965             way = osmWay();
49966
49967         context.perform(
49968             actionAddEntity(node),
49969             actionAddEntity(way),
49970             actionAddVertex(way.id, node.id)
49971         );
49972
49973         context.enter(modeDrawLine(context, way.id, baseGraph));
49974     }
49975
49976
49977     function startFromWay(loc, edge) {
49978         var baseGraph = context.graph(),
49979             node = osmNode({ loc: loc }),
49980             way = osmWay();
49981
49982         context.perform(
49983             actionAddEntity(node),
49984             actionAddEntity(way),
49985             actionAddVertex(way.id, node.id),
49986             actionAddMidpoint({ loc: loc, edge: edge }, node)
49987         );
49988
49989         context.enter(modeDrawLine(context, way.id, baseGraph));
49990     }
49991
49992
49993     function startFromNode(node) {
49994         var baseGraph = context.graph(),
49995             way = osmWay();
49996
49997         context.perform(
49998             actionAddEntity(way),
49999             actionAddVertex(way.id, node.id)
50000         );
50001
50002         context.enter(modeDrawLine(context, way.id, baseGraph));
50003     }
50004
50005
50006     mode.enter = function() {
50007         context.install(behavior);
50008     };
50009
50010
50011     mode.exit = function() {
50012         context.uninstall(behavior);
50013     };
50014
50015     return mode;
50016 }
50017
50018 function modeAddPoint$$1(context) {
50019     var mode = {
50020         id: 'add-point',
50021         button: 'point',
50022         title: t('modes.add_point.title'),
50023         description: t('modes.add_point.description'),
50024         key: '1'
50025     };
50026
50027     var behavior = behaviorDraw(context)
50028         .tail(t('modes.add_point.tail'))
50029         .on('click', add)
50030         .on('clickWay', addWay)
50031         .on('clickNode', addNode)
50032         .on('cancel', cancel)
50033         .on('finish', cancel);
50034
50035
50036     function add(loc) {
50037         var node = osmNode({ loc: loc });
50038
50039         context.perform(
50040             actionAddEntity(node),
50041             t('operations.add.annotation.point')
50042         );
50043
50044         context.enter(
50045             modeSelect(context, [node.id]).suppressMenu(true).newFeature(true)
50046         );
50047     }
50048
50049
50050     function addWay(loc) {
50051         add(loc);
50052     }
50053
50054
50055     function addNode(node) {
50056         add(node.loc);
50057     }
50058
50059
50060     function cancel() {
50061         context.enter(modeBrowse$$1(context));
50062     }
50063
50064
50065     mode.enter = function() {
50066         context.install(behavior);
50067     };
50068
50069
50070     mode.exit = function() {
50071         context.uninstall(behavior);
50072     };
50073
50074
50075     return mode;
50076 }
50077
50078 function modeBrowse$$1(context) {
50079     var mode = {
50080         button: 'browse',
50081         id: 'browse',
50082         title: t('modes.browse.title'),
50083         description: t('modes.browse.description')
50084     }, sidebar;
50085
50086     var behaviors = [
50087         behaviorPaste(context),
50088         behaviorHover(context).on('hover', context.ui().sidebar.hover),
50089         behaviorSelect(context),
50090         behaviorLasso(context),
50091         modeDragNode$$1(context).behavior
50092     ];
50093
50094
50095     mode.enter = function() {
50096         behaviors.forEach(function(behavior) {
50097             context.install(behavior);
50098         });
50099
50100         // Get focus on the body.
50101         if (document.activeElement && document.activeElement.blur) {
50102             document.activeElement.blur();
50103         }
50104
50105         if (sidebar) {
50106             context.ui().sidebar.show(sidebar);
50107         } else {
50108             context.ui().sidebar.select(null);
50109         }
50110     };
50111
50112
50113     mode.exit = function() {
50114         context.ui().sidebar.hover.cancel();
50115         behaviors.forEach(function(behavior) {
50116             context.uninstall(behavior);
50117         });
50118
50119         if (sidebar) {
50120             context.ui().sidebar.hide();
50121         }
50122     };
50123
50124
50125     mode.sidebar = function(_) {
50126         if (!arguments.length) return sidebar;
50127         sidebar = _;
50128         return mode;
50129     };
50130
50131
50132     return mode;
50133 }
50134
50135 function modeDragNode$$1(context) {
50136     var mode = {
50137         id: 'drag-node',
50138         button: 'browse'
50139     };
50140
50141     var nudgeInterval,
50142         activeIDs,
50143         wasMidpoint,
50144         isCancelled,
50145         selectedIDs = [],
50146         hover = behaviorHover(context).altDisables(true).on('hover', context.ui().sidebar.hover),
50147         edit = behaviorEdit(context);
50148
50149
50150     function edge(point, size) {
50151         var pad = [30, 100, 30, 100];
50152         if (point[0] > size[0] - pad[0]) return [-10, 0];
50153         else if (point[0] < pad[2]) return [10, 0];
50154         else if (point[1] > size[1] - pad[1]) return [0, -10];
50155         else if (point[1] < pad[3]) return [0, 10];
50156         return null;
50157     }
50158
50159
50160     function startNudge(nudge) {
50161         if (nudgeInterval) window.clearInterval(nudgeInterval);
50162         nudgeInterval = window.setInterval(function() {
50163             context.pan(nudge);
50164         }, 50);
50165     }
50166
50167
50168     function stopNudge() {
50169         if (nudgeInterval) window.clearInterval(nudgeInterval);
50170         nudgeInterval = null;
50171     }
50172
50173
50174     function moveAnnotation(entity) {
50175         return t('operations.move.annotation.' + entity.geometry(context.graph()));
50176     }
50177
50178
50179     function connectAnnotation(entity) {
50180         return t('operations.connect.annotation.' + entity.geometry(context.graph()));
50181     }
50182
50183
50184     function origin(entity) {
50185         return context.projection(entity.loc);
50186     }
50187
50188
50189     function start(entity) {
50190         isCancelled = event.sourceEvent.shiftKey ||
50191             context.features().hasHiddenConnections(entity, context.graph());
50192
50193         if (isCancelled) return behavior.cancel();
50194
50195         wasMidpoint = entity.type === 'midpoint';
50196         if (wasMidpoint) {
50197             var midpoint = entity;
50198             entity = osmNode();
50199             context.perform(actionAddMidpoint(midpoint, entity));
50200
50201             var vertex = context.surface().selectAll('.' + entity.id);
50202             behavior.target(vertex.node(), entity);
50203
50204         } else {
50205             context.perform(actionNoop());
50206         }
50207
50208         activeIDs = lodash.map(context.graph().parentWays(entity), 'id');
50209         activeIDs.push(entity.id);
50210         context.enter(mode);
50211     }
50212
50213
50214     function datum() {
50215         if (event.sourceEvent.altKey) {
50216             return {};
50217         }
50218
50219         return event.sourceEvent.target.__data__ || {};
50220     }
50221
50222
50223     // via https://gist.github.com/shawnbot/4166283
50224     function childOf(p, c) {
50225         if (p === c) return false;
50226         while (c && c !== p) c = c.parentNode;
50227         return c === p;
50228     }
50229
50230
50231     function move(entity) {
50232         if (isCancelled) return;
50233         event.sourceEvent.stopPropagation();
50234
50235         var nudge = childOf(context.container().node(),
50236             event.sourceEvent.toElement) &&
50237             edge(event.point, context.map().dimensions());
50238
50239         if (nudge) startNudge(nudge);
50240         else stopNudge();
50241
50242         var loc = context.projection.invert(event.point);
50243
50244         var d = datum();
50245         if (d.type === 'node' && d.id !== entity.id) {
50246             loc = d.loc;
50247         } else if (d.type === 'way' && !select(event.sourceEvent.target).classed('fill')) {
50248             loc = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection).loc;
50249         }
50250
50251         context.replace(
50252             actionMoveNode(entity.id, loc),
50253             moveAnnotation(entity)
50254         );
50255     }
50256
50257
50258     function end(entity) {
50259         if (isCancelled) return;
50260
50261         var d = datum();
50262
50263         if (d.type === 'way') {
50264             var choice = geoChooseEdge(context.childNodes(d), context.mouse(), context.projection);
50265             context.replace(
50266                 actionAddMidpoint({ loc: choice.loc, edge: [d.nodes[choice.index - 1], d.nodes[choice.index]] }, entity),
50267                 connectAnnotation(d)
50268             );
50269
50270         } else if (d.type === 'node' && d.id !== entity.id) {
50271             context.replace(
50272                 actionConnect([d.id, entity.id]),
50273                 connectAnnotation(d)
50274             );
50275
50276         } else if (wasMidpoint) {
50277             context.replace(
50278                 actionNoop(),
50279                 t('operations.add.annotation.vertex')
50280             );
50281
50282         } else {
50283             context.replace(
50284                 actionNoop(),
50285                 moveAnnotation(entity)
50286             );
50287         }
50288
50289         var reselection = selectedIDs.filter(function(id) {
50290             return context.graph().hasEntity(id);
50291         });
50292
50293         if (reselection.length) {
50294             context.enter(modeSelect(context, reselection).suppressMenu(true));
50295         } else {
50296             context.enter(modeBrowse$$1(context));
50297         }
50298     }
50299
50300
50301     function cancel() {
50302         behavior.cancel();
50303         context.enter(modeBrowse$$1(context));
50304     }
50305
50306
50307     function setActiveElements() {
50308         context.surface().selectAll(utilEntitySelector(activeIDs))
50309             .classed('active', true);
50310     }
50311
50312
50313     var behavior = behaviorDrag()
50314         .delegate('g.node, g.point, g.midpoint')
50315         .surface(context.surface().node())
50316         .origin(origin)
50317         .on('start', start)
50318         .on('move', move)
50319         .on('end', end);
50320
50321
50322     mode.enter = function() {
50323         context.install(hover);
50324         context.install(edit);
50325
50326         context.history()
50327             .on('undone.drag-node', cancel);
50328
50329         context.map()
50330             .on('drawn.drag-node', setActiveElements);
50331
50332         setActiveElements();
50333     };
50334
50335
50336     mode.exit = function() {
50337         context.ui().sidebar.hover.cancel();
50338         context.uninstall(hover);
50339         context.uninstall(edit);
50340
50341         context.history()
50342             .on('undone.drag-node', null);
50343
50344         context.map()
50345             .on('drawn.drag-node', null);
50346
50347         context.surface()
50348             .selectAll('.active')
50349             .classed('active', false);
50350
50351         stopNudge();
50352     };
50353
50354
50355     mode.selectedIDs = function(_) {
50356         if (!arguments.length) return selectedIDs;
50357         selectedIDs = _;
50358         return mode;
50359     };
50360
50361
50362     mode.behavior = behavior;
50363
50364
50365     return mode;
50366 }
50367
50368 function modeDrawArea(context, wayId, baseGraph) {
50369     var mode = {
50370         button: 'area',
50371         id: 'draw-area'
50372     };
50373
50374     var behavior;
50375
50376
50377     mode.enter = function() {
50378         var way = context.entity(wayId),
50379             headId = way.nodes[way.nodes.length - 2],
50380             tailId = way.first();
50381
50382         behavior = behaviorDrawWay(context, wayId, -1, mode, baseGraph)
50383             .tail(t('modes.draw_area.tail'));
50384
50385         var addNode = behavior.addNode;
50386
50387         behavior.addNode = function(node) {
50388             if (node.id === headId || node.id === tailId) {
50389                 behavior.finish();
50390             } else {
50391                 addNode(node);
50392             }
50393         };
50394
50395         context.install(behavior);
50396     };
50397
50398
50399     mode.exit = function() {
50400         context.uninstall(behavior);
50401     };
50402
50403
50404     mode.selectedIDs = function() {
50405         return [wayId];
50406     };
50407
50408
50409     return mode;
50410 }
50411
50412 function modeDrawLine(context, wayId, baseGraph, affix) {
50413     var mode = {
50414         button: 'line',
50415         id: 'draw-line'
50416     };
50417
50418     var behavior;
50419
50420
50421     mode.enter = function() {
50422         var way = context.entity(wayId),
50423             index = (affix === 'prefix') ? 0 : undefined,
50424             headId = (affix === 'prefix') ? way.first() : way.last();
50425
50426         behavior = behaviorDrawWay(context, wayId, index, mode, baseGraph)
50427             .tail(t('modes.draw_line.tail'));
50428
50429         var addNode = behavior.addNode;
50430
50431         behavior.addNode = function(node) {
50432             if (node.id === headId) {
50433                 behavior.finish();
50434             } else {
50435                 addNode(node);
50436             }
50437         };
50438
50439         context.install(behavior);
50440     };
50441
50442
50443     mode.exit = function() {
50444         context.uninstall(behavior);
50445     };
50446
50447
50448     mode.selectedIDs = function() {
50449         return [wayId];
50450     };
50451
50452
50453     return mode;
50454 }
50455
50456 function modeMove$$1(context, entityIDs, baseGraph) {
50457     var mode = {
50458         id: 'move',
50459         button: 'browse'
50460     };
50461
50462     var keybinding = d3keybinding('move'),
50463         edit = behaviorEdit(context),
50464         annotation = entityIDs.length === 1 ?
50465             t('operations.move.annotation.' + context.geometry(entityIDs[0])) :
50466             t('operations.move.annotation.multiple'),
50467         cache,
50468         origin,
50469         nudgeInterval;
50470
50471
50472     function vecSub(a, b) { return [a[0] - b[0], a[1] - b[1]]; }
50473
50474
50475     function edge(point, size) {
50476         var pad = [30, 100, 30, 100];
50477         if (point[0] > size[0] - pad[0]) return [-10, 0];
50478         else if (point[0] < pad[2]) return [10, 0];
50479         else if (point[1] > size[1] - pad[1]) return [0, -10];
50480         else if (point[1] < pad[3]) return [0, 10];
50481         return null;
50482     }
50483
50484
50485     function startNudge(nudge) {
50486         if (nudgeInterval) window.clearInterval(nudgeInterval);
50487         nudgeInterval = window.setInterval(function() {
50488             context.pan(nudge);
50489
50490             var currMouse = context.mouse(),
50491                 origMouse = context.projection(origin),
50492                 delta = vecSub(vecSub(currMouse, origMouse), nudge),
50493                 action = actionMove(entityIDs, delta, context.projection, cache);
50494
50495             context.overwrite(action, annotation);
50496
50497         }, 50);
50498     }
50499
50500
50501     function stopNudge() {
50502         if (nudgeInterval) window.clearInterval(nudgeInterval);
50503         nudgeInterval = null;
50504     }
50505
50506
50507     function move() {
50508         var currMouse = context.mouse(),
50509             origMouse = context.projection(origin),
50510             delta = vecSub(currMouse, origMouse),
50511             action = actionMove(entityIDs, delta, context.projection, cache);
50512
50513         context.overwrite(action, annotation);
50514
50515         var nudge = edge(currMouse, context.map().dimensions());
50516         if (nudge) startNudge(nudge);
50517         else stopNudge();
50518     }
50519
50520
50521     function finish() {
50522         event.stopPropagation();
50523         context.enter(modeSelect(context, entityIDs).suppressMenu(true));
50524         stopNudge();
50525     }
50526
50527
50528     function cancel() {
50529         if (baseGraph) {
50530             while (context.graph() !== baseGraph) context.pop();
50531             context.enter(modeBrowse$$1(context));
50532         } else {
50533             context.pop();
50534             context.enter(modeSelect(context, entityIDs).suppressMenu(true));
50535         }
50536         stopNudge();
50537     }
50538
50539
50540     function undone() {
50541         context.enter(modeBrowse$$1(context));
50542     }
50543
50544
50545     mode.enter = function() {
50546         origin = context.map().mouseCoordinates();
50547         cache = {};
50548
50549         context.install(edit);
50550
50551         context.perform(
50552             actionNoop(),
50553             annotation
50554         );
50555
50556         context.surface()
50557             .on('mousemove.move', move)
50558             .on('click.move', finish);
50559
50560         context.history()
50561             .on('undone.move', undone);
50562
50563         keybinding
50564             .on('⎋', cancel)
50565             .on('↩', finish);
50566
50567         select(document)
50568             .call(keybinding);
50569     };
50570
50571
50572     mode.exit = function() {
50573         stopNudge();
50574
50575         context.uninstall(edit);
50576
50577         context.surface()
50578             .on('mousemove.move', null)
50579             .on('click.move', null);
50580
50581         context.history()
50582             .on('undone.move', null);
50583
50584         keybinding.off();
50585     };
50586
50587
50588     return mode;
50589 }
50590
50591 function modeRotateWay$$1(context, wayId) {
50592     var mode = {
50593         id: 'rotate-way',
50594         button: 'browse'
50595     };
50596
50597     var keybinding = d3keybinding('rotate-way'),
50598         edit = behaviorEdit(context);
50599
50600
50601     mode.enter = function() {
50602         context.install(edit);
50603
50604         var annotation = t('operations.rotate.annotation.' + context.geometry(wayId)),
50605             way = context.graph().entity(wayId),
50606             nodes = lodash.uniq(context.graph().childNodes(way)),
50607             points = nodes.map(function(n) { return context.projection(n.loc); }),
50608             pivot = d3polygonCentroid(points),
50609             angle;
50610
50611         context.perform(
50612             actionNoop(),
50613             annotation
50614         );
50615
50616         context.surface()
50617             .on('mousemove.rotate-way', rotate)
50618             .on('click.rotate-way', finish);
50619
50620         context.history()
50621             .on('undone.rotate-way', undone);
50622
50623         keybinding
50624             .on('⎋', cancel)
50625             .on('↩', finish);
50626
50627         select(document)
50628             .call(keybinding);
50629
50630
50631         function rotate() {
50632             var mousePoint = context.mouse(),
50633                 newAngle = Math.atan2(mousePoint[1] - pivot[1], mousePoint[0] - pivot[0]);
50634
50635             if (typeof angle === 'undefined') angle = newAngle;
50636
50637             context.replace(
50638                 actionRotateWay(wayId, pivot, newAngle - angle, context.projection),
50639                 annotation
50640             );
50641
50642             angle = newAngle;
50643         }
50644
50645
50646         function finish() {
50647             event.stopPropagation();
50648             context.enter(modeSelect(context, [wayId]).suppressMenu(true));
50649         }
50650
50651
50652         function cancel() {
50653             context.pop();
50654             context.enter(modeSelect(context, [wayId]).suppressMenu(true));
50655         }
50656
50657
50658         function undone() {
50659             context.enter(modeBrowse$$1(context));
50660         }
50661     };
50662
50663
50664     mode.exit = function() {
50665         context.uninstall(edit);
50666
50667         context.surface()
50668             .on('mousemove.rotate-way', null)
50669             .on('click.rotate-way', null);
50670
50671         context.history()
50672             .on('undone.rotate-way', null);
50673
50674         keybinding.off();
50675     };
50676
50677
50678     return mode;
50679 }
50680
50681 function modeSave$$1(context) {
50682     var mode = {
50683         id: 'save'
50684     };
50685
50686     var ui = uiCommit(context)
50687             .on('cancel', cancel)
50688             .on('save', save);
50689
50690
50691     function cancel() {
50692         context.enter(modeBrowse$$1(context));
50693     }
50694
50695
50696     function save(e, tryAgain) {
50697         function withChildNodes(ids, graph) {
50698             return lodash.uniq(lodash.reduce(ids, function(result, id) {
50699                 var e = graph.entity(id);
50700                 if (e.type === 'way') {
50701                     try {
50702                         var cn = graph.childNodes(e);
50703                         result.push.apply(result, lodash.map(lodash.filter(cn, 'version'), 'id'));
50704                     } catch (err) {
50705                         /* eslint-disable no-console */
50706                         if (typeof console !== 'undefined') console.error(err);
50707                         /* eslint-enable no-console */
50708                     }
50709                 }
50710                 return result;
50711             }, lodash.clone(ids)));
50712         }
50713
50714         var loading = uiLoading(context).message(t('save.uploading')).blocking(true),
50715             history = context.history(),
50716             origChanges = history.changes(actionDiscardTags(history.difference())),
50717             localGraph = context.graph(),
50718             remoteGraph = coreGraph$$1(history.base(), true),
50719             modified = lodash.filter(history.difference().summary(), {changeType: 'modified'}),
50720             toCheck = lodash.map(lodash.map(modified, 'entity'), 'id'),
50721             toLoad = withChildNodes(toCheck, localGraph),
50722             conflicts = [],
50723             errors = [];
50724
50725         if (!tryAgain) history.perform(actionNoop());  // checkpoint
50726         context.container().call(loading);
50727
50728         if (toCheck.length) {
50729             context.connection().loadMultiple(toLoad, loaded);
50730         } else {
50731             finalize();
50732         }
50733
50734
50735         // Reload modified entities into an alternate graph and check for conflicts..
50736         function loaded(err, result) {
50737             if (errors.length) return;
50738
50739             if (err) {
50740                 errors.push({
50741                     msg: err.responseText,
50742                     details: [ t('save.status_code', { code: err.status }) ]
50743                 });
50744                 showErrors();
50745
50746             } else {
50747                 var loadMore = [];
50748                 lodash.each(result.data, function(entity) {
50749                     remoteGraph.replace(entity);
50750                     toLoad = lodash.without(toLoad, entity.id);
50751
50752                     // Because loadMultiple doesn't download /full like loadEntity,
50753                     // need to also load children that aren't already being checked..
50754                     if (!entity.visible) return;
50755                     if (entity.type === 'way') {
50756                         loadMore.push.apply(loadMore,
50757                             lodash.difference(entity.nodes, toCheck, toLoad, loadMore));
50758                     } else if (entity.type === 'relation' && entity.isMultipolygon()) {
50759                         loadMore.push.apply(loadMore,
50760                             lodash.difference(lodash.map(entity.members, 'id'), toCheck, toLoad, loadMore));
50761                     }
50762                 });
50763
50764                 if (loadMore.length) {
50765                     toLoad.push.apply(toLoad, loadMore);
50766                     context.connection().loadMultiple(loadMore, loaded);
50767                 }
50768
50769                 if (!toLoad.length) {
50770                     checkConflicts();
50771                 }
50772             }
50773         }
50774
50775
50776         function checkConflicts() {
50777             function choice(id, text$$1, action) {
50778                 return { id: id, text: text$$1, action: function() { history.replace(action); } };
50779             }
50780             function formatUser(d) {
50781                 return '<a href="' + context.connection().userURL(d) + '" target="_blank">' + d + '</a>';
50782             }
50783             function entityName(entity) {
50784                 return utilDisplayName(entity) || (utilDisplayType(entity.id) + ' ' + entity.id);
50785             }
50786
50787             function compareVersions(local$$1, remote) {
50788                 if (local$$1.version !== remote.version) return false;
50789
50790                 if (local$$1.type === 'way') {
50791                     var children = lodash.union(local$$1.nodes, remote.nodes);
50792
50793                     for (var i = 0; i < children.length; i++) {
50794                         var a = localGraph.hasEntity(children[i]),
50795                             b = remoteGraph.hasEntity(children[i]);
50796
50797                         if (a && b && a.version !== b.version) return false;
50798                     }
50799                 }
50800
50801                 return true;
50802             }
50803
50804             lodash.each(toCheck, function(id) {
50805                 var local$$1 = localGraph.entity(id),
50806                     remote = remoteGraph.entity(id);
50807
50808                 if (compareVersions(local$$1, remote)) return;
50809
50810                 var action = actionMergeRemoteChanges,
50811                     merge$$1 = action(id, localGraph, remoteGraph, formatUser);
50812
50813                 history.replace(merge$$1);
50814
50815                 var mergeConflicts = merge$$1.conflicts();
50816                 if (!mergeConflicts.length) return;  // merged safely
50817
50818                 var forceLocal = action(id, localGraph, remoteGraph).withOption('force_local'),
50819                     forceRemote = action(id, localGraph, remoteGraph).withOption('force_remote'),
50820                     keepMine = t('save.conflict.' + (remote.visible ? 'keep_local' : 'restore')),
50821                     keepTheirs = t('save.conflict.' + (remote.visible ? 'keep_remote' : 'delete'));
50822
50823                 conflicts.push({
50824                     id: id,
50825                     name: entityName(local$$1),
50826                     details: mergeConflicts,
50827                     chosen: 1,
50828                     choices: [
50829                         choice(id, keepMine, forceLocal),
50830                         choice(id, keepTheirs, forceRemote)
50831                     ]
50832                 });
50833             });
50834
50835             finalize();
50836         }
50837
50838
50839         function finalize() {
50840             if (conflicts.length) {
50841                 conflicts.sort(function(a,b) { return b.id.localeCompare(a.id); });
50842                 showConflicts();
50843             } else if (errors.length) {
50844                 showErrors();
50845             } else {
50846                 var changes = history.changes(actionDiscardTags(history.difference()));
50847                 if (changes.modified.length || changes.created.length || changes.deleted.length) {
50848                     context.connection().putChangeset(
50849                         changes,
50850                         context.version,
50851                         e.comment,
50852                         history.imageryUsed(),
50853                         function(err, changeset_id) {
50854                             if (err) {
50855                                 errors.push({
50856                                     msg: err.responseText,
50857                                     details: [ t('save.status_code', { code: err.status }) ]
50858                                 });
50859                                 showErrors();
50860                             } else {
50861                                 history.clearSaved();
50862                                 success(e, changeset_id);
50863                                 // Add delay to allow for postgres replication #1646 #2678
50864                                 window.setTimeout(function() {
50865                                     loading.close();
50866                                     context.flush();
50867                                 }, 2500);
50868                             }
50869                         });
50870                 } else {        // changes were insignificant or reverted by user
50871                     loading.close();
50872                     context.flush();
50873                     cancel();
50874                 }
50875             }
50876         }
50877
50878
50879         function showConflicts() {
50880             var selection$$1 = context.container()
50881                 .select('#sidebar')
50882                 .append('div')
50883                 .attr('class','sidebar-component');
50884
50885             loading.close();
50886
50887             selection$$1.call(uiConflicts(context)
50888                 .list(conflicts)
50889                 .on('download', function() {
50890                     var data = JXON.stringify(context.connection().osmChangeJXON('CHANGEME', origChanges)),
50891                         win = window.open('data:text/xml,' + encodeURIComponent(data), '_blank');
50892                     win.focus();
50893                 })
50894                 .on('cancel', function() {
50895                     history.pop();
50896                     selection$$1.remove();
50897                 })
50898                 .on('save', function() {
50899                     for (var i = 0; i < conflicts.length; i++) {
50900                         if (conflicts[i].chosen === 1) {  // user chose "keep theirs"
50901                             var entity = context.hasEntity(conflicts[i].id);
50902                             if (entity && entity.type === 'way') {
50903                                 var children = lodash.uniq(entity.nodes);
50904                                 for (var j = 0; j < children.length; j++) {
50905                                     history.replace(actionRevert(children[j]));
50906                                 }
50907                             }
50908                             history.replace(actionRevert(conflicts[i].id));
50909                         }
50910                     }
50911
50912                     selection$$1.remove();
50913                     save(e, true);
50914                 })
50915             );
50916         }
50917
50918
50919         function showErrors() {
50920             var selection$$1 = uiConfirm(context.container());
50921
50922             history.pop();
50923             loading.close();
50924
50925             selection$$1
50926                 .select('.modal-section.header')
50927                 .append('h3')
50928                 .text(t('save.error'));
50929
50930             addErrors(selection$$1, errors);
50931             selection$$1.okButton();
50932         }
50933
50934
50935         function addErrors(selection$$1, data) {
50936             var message = selection$$1
50937                 .select('.modal-section.message-text');
50938
50939             var items = message
50940                 .selectAll('.error-container')
50941                 .data(data);
50942
50943             var enter = items.enter()
50944                 .append('div')
50945                 .attr('class', 'error-container');
50946
50947             enter
50948                 .append('a')
50949                 .attr('class', 'error-description')
50950                 .attr('href', '#')
50951                 .classed('hide-toggle', true)
50952                 .text(function(d) { return d.msg || t('save.unknown_error_details'); })
50953                 .on('click', function() {
50954                     var error = select(this),
50955                         detail = select(this.nextElementSibling),
50956                         exp = error.classed('expanded');
50957
50958                     detail.style('display', exp ? 'none' : 'block');
50959                     error.classed('expanded', !exp);
50960
50961                     event.preventDefault();
50962                 });
50963
50964             var details = enter
50965                 .append('div')
50966                 .attr('class', 'error-detail-container')
50967                 .style('display', 'none');
50968
50969             details
50970                 .append('ul')
50971                 .attr('class', 'error-detail-list')
50972                 .selectAll('li')
50973                 .data(function(d) { return d.details || []; })
50974                 .enter()
50975                 .append('li')
50976                 .attr('class', 'error-detail-item')
50977                 .text(function(d) { return d; });
50978
50979             items.exit()
50980                 .remove();
50981         }
50982
50983     }
50984
50985
50986     function success(e, changeset_id) {
50987         context.enter(modeBrowse$$1(context)
50988             .sidebar(uiSuccess(context)
50989                 .changeset({
50990                     id: changeset_id,
50991                     comment: e.comment
50992                 })
50993                 .on('cancel', function() {
50994                     context.ui().sidebar.hide();
50995                 })
50996             )
50997         );
50998     }
50999
51000
51001     mode.enter = function() {
51002         context.connection().authenticate(function(err) {
51003             if (err) {
51004                 cancel();
51005             } else {
51006                 context.ui().sidebar.show(ui);
51007             }
51008         });
51009     };
51010
51011
51012     mode.exit = function() {
51013         context.ui().sidebar.hide();
51014     };
51015
51016     return mode;
51017 }
51018
51019 function operationCircularize(selectedIDs, context) {
51020     var entityId = selectedIDs[0],
51021         entity = context.entity(entityId),
51022         extent = entity.extent(context.graph()),
51023         geometry = context.geometry(entityId),
51024         action = actionCircularize(entityId, context.projection);
51025
51026     var operation = function() {
51027         var annotation = t('operations.circularize.annotation.' + geometry);
51028         context.perform(action, annotation);
51029     };
51030
51031
51032     operation.available = function() {
51033         return selectedIDs.length === 1 &&
51034             entity.type === 'way' &&
51035             lodash.uniq(entity.nodes).length > 1;
51036     };
51037
51038
51039     operation.disabled = function() {
51040         var reason;
51041         if (extent.percentContainedIn(context.extent()) < 0.8) {
51042             reason = 'too_large';
51043         } else if (context.hasHiddenConnections(entityId)) {
51044             reason = 'connected_to_hidden';
51045         }
51046         return action.disabled(context.graph()) || reason;
51047     };
51048
51049
51050     operation.tooltip = function() {
51051         var disable = operation.disabled();
51052         return disable ?
51053             t('operations.circularize.' + disable) :
51054             t('operations.circularize.description.' + geometry);
51055     };
51056
51057
51058     operation.id = 'circularize';
51059     operation.keys = [t('operations.circularize.key')];
51060     operation.title = t('operations.circularize.title');
51061
51062
51063     return operation;
51064 }
51065
51066 function operationContinue(selectedIDs, context) {
51067     var graph = context.graph(),
51068         entities = selectedIDs.map(function(id) { return graph.entity(id); }),
51069         geometries = lodash.extend({ line: [], vertex: [] },
51070             lodash.groupBy(entities, function(entity) { return entity.geometry(graph); })),
51071         vertex = geometries.vertex[0];
51072
51073
51074     function candidateWays() {
51075         return graph.parentWays(vertex).filter(function(parent) {
51076             return parent.geometry(graph) === 'line' &&
51077                 parent.affix(vertex.id) &&
51078                 (geometries.line.length === 0 || geometries.line[0] === parent);
51079         });
51080     }
51081
51082
51083     var operation = function() {
51084         var candidate = candidateWays()[0];
51085         context.enter(
51086             modeDrawLine(context, candidate.id, context.graph(), candidate.affix(vertex.id))
51087         );
51088     };
51089
51090
51091     operation.available = function() {
51092         return geometries.vertex.length === 1 && geometries.line.length <= 1 &&
51093             !context.features().hasHiddenConnections(vertex, context.graph());
51094     };
51095
51096
51097     operation.disabled = function() {
51098         var candidates = candidateWays();
51099         if (candidates.length === 0)
51100             return 'not_eligible';
51101         if (candidates.length > 1)
51102             return 'multiple';
51103     };
51104
51105
51106     operation.tooltip = function() {
51107         var disable = operation.disabled();
51108         return disable ?
51109             t('operations.continue.' + disable) :
51110             t('operations.continue.description');
51111     };
51112
51113
51114     operation.id = 'continue';
51115     operation.keys = [t('operations.continue.key')];
51116     operation.title = t('operations.continue.title');
51117
51118
51119     return operation;
51120 }
51121
51122 function operationDelete(selectedIDs, context) {
51123     var action = actionDeleteMultiple(selectedIDs);
51124
51125     var operation = function() {
51126         var annotation,
51127             nextSelectedID;
51128
51129         if (selectedIDs.length > 1) {
51130             annotation = t('operations.delete.annotation.multiple', { n: selectedIDs.length });
51131
51132         } else {
51133             var id = selectedIDs[0],
51134                 entity = context.entity(id),
51135                 geometry = context.geometry(id),
51136                 parents = context.graph().parentWays(entity),
51137                 parent = parents[0];
51138
51139             annotation = t('operations.delete.annotation.' + geometry);
51140
51141             // Select the next closest node in the way.
51142             if (geometry === 'vertex' && parents.length === 1 && parent.nodes.length > 2) {
51143                 var nodes = parent.nodes,
51144                     i = nodes.indexOf(id);
51145
51146                 if (i === 0) {
51147                     i++;
51148                 } else if (i === nodes.length - 1) {
51149                     i--;
51150                 } else {
51151                     var a = geoSphericalDistance(entity.loc, context.entity(nodes[i - 1]).loc),
51152                         b = geoSphericalDistance(entity.loc, context.entity(nodes[i + 1]).loc);
51153                     i = a < b ? i - 1 : i + 1;
51154                 }
51155
51156                 nextSelectedID = nodes[i];
51157             }
51158         }
51159
51160         if (nextSelectedID && context.hasEntity(nextSelectedID)) {
51161             context.enter(modeSelect(context, [nextSelectedID]));
51162         } else {
51163             context.enter(modeBrowse$$1(context));
51164         }
51165
51166         context.perform(action, annotation);
51167     };
51168
51169
51170     operation.available = function() {
51171         return true;
51172     };
51173
51174
51175     operation.disabled = function() {
51176         var reason;
51177         if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51178             reason = 'connected_to_hidden';
51179         }
51180         return action.disabled(context.graph()) || reason;
51181     };
51182
51183
51184     operation.tooltip = function() {
51185         var disable = operation.disabled();
51186         return disable ?
51187             t('operations.delete.' + disable) :
51188             t('operations.delete.description');
51189     };
51190
51191
51192     operation.id = 'delete';
51193     operation.keys = [uiCmd('⌘⌫'), uiCmd('⌘⌦'), uiCmd('⌦')];
51194     operation.title = t('operations.delete.title');
51195
51196
51197     return operation;
51198 }
51199
51200 function operationDisconnect(selectedIDs, context) {
51201     var vertices = lodash.filter(selectedIDs, function(entityId) {
51202         return context.geometry(entityId) === 'vertex';
51203     });
51204
51205     var entityId = vertices[0],
51206         action = actionDisconnect(entityId);
51207
51208     if (selectedIDs.length > 1) {
51209         action.limitWays(lodash.without(selectedIDs, entityId));
51210     }
51211
51212     var operation = function() {
51213         context.perform(action, t('operations.disconnect.annotation'));
51214     };
51215
51216
51217     operation.available = function() {
51218         return vertices.length === 1;
51219     };
51220
51221
51222     operation.disabled = function() {
51223         var reason;
51224         if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51225             reason = 'connected_to_hidden';
51226         }
51227         return action.disabled(context.graph()) || reason;
51228     };
51229
51230
51231     operation.tooltip = function() {
51232         var disable = operation.disabled();
51233         return disable ?
51234             t('operations.disconnect.' + disable) :
51235             t('operations.disconnect.description');
51236     };
51237
51238
51239     operation.id = 'disconnect';
51240     operation.keys = [t('operations.disconnect.key')];
51241     operation.title = t('operations.disconnect.title');
51242
51243
51244     return operation;
51245 }
51246
51247 function operationMerge(selectedIDs, context) {
51248     var join = actionJoin(selectedIDs),
51249         merge = actionMerge(selectedIDs),
51250         mergePolygon = actionMergePolygon(selectedIDs);
51251
51252     var operation = function() {
51253         var annotation = t('operations.merge.annotation', {n: selectedIDs.length}),
51254             action;
51255
51256         if (!join.disabled(context.graph())) {
51257             action = join;
51258         } else if (!merge.disabled(context.graph())) {
51259             action = merge;
51260         } else {
51261             action = mergePolygon;
51262         }
51263
51264         context.perform(action, annotation);
51265         var ids = selectedIDs.filter(function(id) { return context.hasEntity(id); });
51266         context.enter(modeSelect(context, ids).suppressMenu(true));
51267     };
51268
51269
51270     operation.available = function() {
51271         return selectedIDs.length >= 2;
51272     };
51273
51274
51275     operation.disabled = function() {
51276         return join.disabled(context.graph()) &&
51277             merge.disabled(context.graph()) &&
51278             mergePolygon.disabled(context.graph());
51279     };
51280
51281
51282     operation.tooltip = function() {
51283         var j = join.disabled(context.graph()),
51284             m = merge.disabled(context.graph()),
51285             p = mergePolygon.disabled(context.graph());
51286
51287         if (j === 'restriction' && m && p) {
51288             return t('operations.merge.restriction',
51289                 { relation: context.presets().item('type/restriction').name() });
51290         }
51291
51292         if (p === 'incomplete_relation' && j && m) {
51293             return t('operations.merge.incomplete_relation');
51294         }
51295
51296         if (j && m && p) {
51297             return t('operations.merge.' + j);
51298         }
51299
51300         return t('operations.merge.description');
51301     };
51302
51303
51304     operation.id = 'merge';
51305     operation.keys = [t('operations.merge.key')];
51306     operation.title = t('operations.merge.title');
51307
51308
51309     return operation;
51310 }
51311
51312 function operationMove(selectedIDs, context) {
51313     var extent = selectedIDs.reduce(function(extent, id) {
51314             return extent.extend(context.entity(id).extent(context.graph()));
51315         }, geoExtent$$1());
51316
51317     var operation = function() {
51318         context.enter(modeMove$$1(context, selectedIDs));
51319     };
51320
51321
51322     operation.available = function() {
51323         return selectedIDs.length > 1 ||
51324             context.entity(selectedIDs[0]).type !== 'node';
51325     };
51326
51327
51328     operation.disabled = function() {
51329         var reason;
51330         if (extent.area() && extent.percentContainedIn(context.extent()) < 0.8) {
51331             reason = 'too_large';
51332         } else if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51333             reason = 'connected_to_hidden';
51334         }
51335
51336         return actionMove(selectedIDs).disabled(context.graph()) || reason;
51337     };
51338
51339
51340     operation.tooltip = function() {
51341         var disable = operation.disabled();
51342         return disable ?
51343             t('operations.move.' + disable) :
51344             t('operations.move.description');
51345     };
51346
51347
51348     operation.id = 'move';
51349     operation.keys = [t('operations.move.key')];
51350     operation.title = t('operations.move.title');
51351
51352
51353     return operation;
51354 }
51355
51356 function operationOrthogonalize(selectedIDs, context) {
51357     var entityId = selectedIDs[0],
51358         entity = context.entity(entityId),
51359         extent = entity.extent(context.graph()),
51360         geometry = context.geometry(entityId),
51361         action = actionOrthogonalize(entityId, context.projection);
51362
51363     var operation = function() {
51364         var annotation = t('operations.orthogonalize.annotation.' + geometry);
51365         context.perform(action, annotation);
51366     };
51367
51368
51369     operation.available = function() {
51370         return selectedIDs.length === 1 &&
51371             entity.type === 'way' &&
51372             entity.isClosed() &&
51373             lodash.uniq(entity.nodes).length > 2;
51374     };
51375
51376
51377     operation.disabled = function() {
51378         var reason;
51379         if (extent.percentContainedIn(context.extent()) < 0.8) {
51380             reason = 'too_large';
51381         } else if (context.hasHiddenConnections(entityId)) {
51382             reason = 'connected_to_hidden';
51383         }
51384         return action.disabled(context.graph()) || reason;
51385     };
51386
51387
51388     operation.tooltip = function() {
51389         var disable = operation.disabled();
51390         return disable ?
51391             t('operations.orthogonalize.' + disable) :
51392             t('operations.orthogonalize.description.' + geometry);
51393     };
51394
51395
51396     operation.id = 'orthogonalize';
51397     operation.keys = [t('operations.orthogonalize.key')];
51398     operation.title = t('operations.orthogonalize.title');
51399
51400
51401     return operation;
51402 }
51403
51404 function operationReverse(selectedIDs, context) {
51405     var entityId = selectedIDs[0];
51406
51407     var operation = function() {
51408         context.perform(
51409             actionReverse(entityId),
51410             t('operations.reverse.annotation')
51411         );
51412     };
51413
51414
51415     operation.available = function() {
51416         return selectedIDs.length === 1 &&
51417             context.geometry(entityId) === 'line';
51418     };
51419
51420
51421     operation.disabled = function() {
51422         return false;
51423     };
51424
51425
51426     operation.tooltip = function() {
51427         return t('operations.reverse.description');
51428     };
51429
51430
51431     operation.id = 'reverse';
51432     operation.keys = [t('operations.reverse.key')];
51433     operation.title = t('operations.reverse.title');
51434
51435
51436     return operation;
51437 }
51438
51439 function operationRotate(selectedIDs, context) {
51440     var entityId = selectedIDs[0],
51441         entity = context.entity(entityId),
51442         extent = entity.extent(context.graph()),
51443         geometry = context.geometry(entityId);
51444
51445     var operation = function() {
51446         context.enter(modeRotateWay$$1(context, entityId));
51447     };
51448
51449
51450     operation.available = function() {
51451         if (selectedIDs.length !== 1 || entity.type !== 'way')
51452             return false;
51453         if (geometry === 'area')
51454             return true;
51455         if (entity.isClosed() &&
51456             context.graph().parentRelations(entity).some(function(r) { return r.isMultipolygon(); }))
51457             return true;
51458         return false;
51459     };
51460
51461
51462     operation.disabled = function() {
51463         if (extent.percentContainedIn(context.extent()) < 0.8) {
51464             return 'too_large';
51465         } else if (context.hasHiddenConnections(entityId)) {
51466             return 'connected_to_hidden';
51467         } else {
51468             return false;
51469         }
51470     };
51471
51472
51473     operation.tooltip = function() {
51474         var disable = operation.disabled();
51475         return disable ?
51476             t('operations.rotate.' + disable) :
51477             t('operations.rotate.description');
51478     };
51479
51480
51481     operation.id = 'rotate';
51482     operation.keys = [t('operations.rotate.key')];
51483     operation.title = t('operations.rotate.title');
51484
51485
51486     return operation;
51487 }
51488
51489 function operationSplit(selectedIDs, context) {
51490     var vertices = lodash.filter(selectedIDs, function(entityId) {
51491         return context.geometry(entityId) === 'vertex';
51492     });
51493
51494     var entityId = vertices[0],
51495         action = actionSplit(entityId);
51496
51497     if (selectedIDs.length > 1) {
51498         action.limitWays(lodash.without(selectedIDs, entityId));
51499     }
51500
51501
51502     var operation = function() {
51503         var annotation;
51504
51505         var ways = action.ways(context.graph());
51506         if (ways.length === 1) {
51507             annotation = t('operations.split.annotation.' + context.geometry(ways[0].id));
51508         } else {
51509             annotation = t('operations.split.annotation.multiple', {n: ways.length});
51510         }
51511
51512         var difference = context.perform(action, annotation);
51513         context.enter(modeSelect(context, difference.extantIDs()));
51514     };
51515
51516
51517     operation.available = function() {
51518         return vertices.length === 1;
51519     };
51520
51521
51522     operation.disabled = function() {
51523         var reason;
51524         if (lodash.some(selectedIDs, context.hasHiddenConnections)) {
51525             reason = 'connected_to_hidden';
51526         }
51527         return action.disabled(context.graph()) || reason;
51528     };
51529
51530
51531     operation.tooltip = function() {
51532         var disable = operation.disabled();
51533         if (disable) {
51534             return t('operations.split.' + disable);
51535         }
51536
51537         var ways = action.ways(context.graph());
51538         if (ways.length === 1) {
51539             return t('operations.split.description.' + context.geometry(ways[0].id));
51540         } else {
51541             return t('operations.split.description.multiple');
51542         }
51543     };
51544
51545
51546     operation.id = 'split';
51547     operation.keys = [t('operations.split.key')];
51548     operation.title = t('operations.split.title');
51549
51550
51551     return operation;
51552 }
51553
51554 function operationStraighten(selectedIDs, context) {
51555     var entityId = selectedIDs[0],
51556         action = actionStraighten(entityId, context.projection);
51557
51558
51559     function operation() {
51560         var annotation = t('operations.straighten.annotation');
51561         context.perform(action, annotation);
51562     }
51563
51564
51565     operation.available = function() {
51566         var entity = context.entity(entityId);
51567         return selectedIDs.length === 1 &&
51568             entity.type === 'way' &&
51569             !entity.isClosed() &&
51570             lodash.uniq(entity.nodes).length > 2;
51571     };
51572
51573
51574     operation.disabled = function() {
51575         var reason;
51576         if (context.hasHiddenConnections(entityId)) {
51577             reason = 'connected_to_hidden';
51578         }
51579         return action.disabled(context.graph()) || reason;
51580     };
51581
51582
51583     operation.tooltip = function() {
51584         var disable = operation.disabled();
51585         return disable ?
51586             t('operations.straighten.' + disable) :
51587             t('operations.straighten.description');
51588     };
51589
51590
51591     operation.id = 'straighten';
51592     operation.keys = [t('operations.straighten.key')];
51593     operation.title = t('operations.straighten.title');
51594
51595
51596     return operation;
51597 }
51598
51599
51600
51601 var Operations = Object.freeze({
51602         operationCircularize: operationCircularize,
51603         operationContinue: operationContinue,
51604         operationDelete: operationDelete,
51605         operationDisconnect: operationDisconnect,
51606         operationMerge: operationMerge,
51607         operationMove: operationMove,
51608         operationOrthogonalize: operationOrthogonalize,
51609         operationReverse: operationReverse,
51610         operationRotate: operationRotate,
51611         operationSplit: operationSplit,
51612         operationStraighten: operationStraighten
51613 });
51614
51615 // Translate a MacOS key command into the appropriate Windows/Linux equivalent.
51616 // For example, ⌘Z -> Ctrl+Z
51617 function uiCmd(code) {
51618     var detected = utilDetect();
51619
51620     if (detected.os === 'mac') {
51621         return code;
51622     }
51623
51624     if (detected.os === 'win') {
51625         if (code === '⌘⇧Z') return 'Ctrl+Y';
51626     }
51627
51628     var result = '',
51629         replacements = {
51630             '⌘': 'Ctrl',
51631             '⇧': 'Shift',
51632             '⌥': 'Alt',
51633             '⌫': 'Backspace',
51634             '⌦': 'Delete'
51635         };
51636
51637     for (var i = 0; i < code.length; i++) {
51638         if (code[i] in replacements) {
51639             result += replacements[code[i]] + (i < code.length - 1 ? '+' : '');
51640         } else {
51641             result += code[i];
51642         }
51643     }
51644
51645     return result;
51646 }
51647
51648 var relatedParent;
51649
51650
51651 function modeSelect(context, selectedIDs) {
51652     var mode = {
51653         id: 'select',
51654         button: 'browse'
51655     };
51656
51657     var keybinding = d3keybinding('select'),
51658         timeout$$1 = null,
51659         behaviors = [
51660             behaviorCopy(context),
51661             behaviorPaste(context),
51662             behaviorBreathe(context),
51663             behaviorHover(context),
51664             behaviorSelect(context),
51665             behaviorLasso(context),
51666             modeDragNode$$1(context).selectedIDs(selectedIDs).behavior
51667         ],
51668         inspector,
51669         radialMenu,
51670         newFeature = false,
51671         suppressMenu = false,
51672         follow = false;
51673
51674
51675     var wrap = context.container()
51676         .select('.inspector-wrap');
51677
51678
51679     function singular() {
51680         if (selectedIDs.length === 1) {
51681             return context.hasEntity(selectedIDs[0]);
51682         }
51683     }
51684
51685
51686     // find the common parent ways for nextVertex, previousVertex
51687     function commonParents() {
51688         var graph = context.graph(),
51689             commonParents = [];
51690
51691         for (var i = 0; i < selectedIDs.length; i++) {
51692             var entity = context.hasEntity(selectedIDs[i]);
51693             if (!entity || entity.geometry(graph) !== 'vertex') {
51694                 return [];  // selection includes some not vertexes
51695             }
51696
51697             var currParents = lodash.map(graph.parentWays(entity), 'id');
51698             if (!commonParents.length) {
51699                 commonParents = currParents;
51700                 continue;
51701             }
51702
51703             commonParents = lodash.intersection(commonParents, currParents);
51704             if (!commonParents.length) {
51705                 return [];
51706             }
51707         }
51708
51709         return commonParents;
51710     }
51711
51712
51713     function singularParent() {
51714         var parents = commonParents();
51715         if (!parents) {
51716             relatedParent = null;
51717             return null;
51718         }
51719
51720         // relatedParent is used when we visit a vertex with multiple
51721         // parents, and we want to remember which parent line we started on.
51722
51723         if (parents.length === 1) {
51724             relatedParent = parents[0];  // remember this parent for later
51725             return relatedParent;
51726         }
51727
51728         if (parents.indexOf(relatedParent) !== -1) {
51729             return relatedParent;   // prefer the previously seen parent
51730         }
51731
51732         return parents[0];
51733     }
51734
51735
51736     function closeMenu() {
51737         if (radialMenu) {
51738             context.surface().call(radialMenu.close);
51739         }
51740     }
51741
51742
51743     function positionMenu() {
51744         if (suppressMenu || !radialMenu) { return; }
51745
51746         var entity = singular();
51747         if (entity && context.geometry(entity.id) === 'relation') {
51748             suppressMenu = true;
51749         } else if (entity && entity.type === 'node') {
51750             radialMenu.center(context.projection(entity.loc));
51751         } else {
51752             var point = context.mouse(),
51753                 viewport = geoExtent$$1(context.projection.clipExtent()).polygon();
51754             if (geoPointInPolygon(point, viewport)) {
51755                 radialMenu.center(point);
51756             } else {
51757                 suppressMenu = true;
51758             }
51759         }
51760     }
51761
51762
51763     function showMenu() {
51764         closeMenu();
51765         if (!suppressMenu && radialMenu) {
51766             context.surface().call(radialMenu);
51767         }
51768     }
51769
51770
51771     function toggleMenu() {
51772         if (select('.radial-menu').empty()) {
51773             showMenu();
51774         } else {
51775             closeMenu();
51776         }
51777     }
51778
51779
51780     mode.selectedIDs = function() {
51781         return selectedIDs;
51782     };
51783
51784
51785     mode.reselect = function() {
51786         var surfaceNode = context.surface().node();
51787         if (surfaceNode.focus) {   // FF doesn't support it
51788             surfaceNode.focus();
51789         }
51790
51791         positionMenu();
51792         showMenu();
51793     };
51794
51795
51796     mode.newFeature = function(_) {
51797         if (!arguments.length) return newFeature;
51798         newFeature = _;
51799         return mode;
51800     };
51801
51802
51803     mode.suppressMenu = function(_) {
51804         if (!arguments.length) return suppressMenu;
51805         suppressMenu = _;
51806         return mode;
51807     };
51808
51809
51810     mode.follow = function(_) {
51811         if (!arguments.length) return follow;
51812         follow = _;
51813         return mode;
51814     };
51815
51816
51817     mode.enter = function() {
51818
51819         function update() {
51820             closeMenu();
51821             if (lodash.some(selectedIDs, function(id) { return !context.hasEntity(id); })) {
51822                 // Exit mode if selected entity gets undone
51823                 context.enter(modeBrowse$$1(context));
51824             }
51825         }
51826
51827
51828         function dblclick() {
51829             var target = select(event.target),
51830                 datum = target.datum();
51831
51832             if (datum instanceof osmWay && !target.classed('fill')) {
51833                 var choice = geoChooseEdge(context.childNodes(datum), context.mouse(), context.projection),
51834                     node = osmNode();
51835
51836                 var prev = datum.nodes[choice.index - 1],
51837                     next = datum.nodes[choice.index];
51838
51839                 context.perform(
51840                     actionAddMidpoint({loc: choice.loc, edge: [prev, next]}, node),
51841                     t('operations.add.annotation.vertex')
51842                 );
51843
51844                 event.preventDefault();
51845                 event.stopPropagation();
51846             }
51847         }
51848
51849
51850         function selectElements(drawn) {
51851             var surface = context.surface(),
51852                 entity = singular();
51853
51854             if (entity && context.geometry(entity.id) === 'relation') {
51855                 suppressMenu = true;
51856                 return;
51857             }
51858
51859             surface.selectAll('.related')
51860                 .classed('related', false);
51861
51862             singularParent();
51863             if (relatedParent) {
51864                 surface.selectAll(utilEntitySelector([relatedParent]))
51865                     .classed('related', true);
51866             }
51867
51868             var selection$$1 = context.surface()
51869                 .selectAll(utilEntityOrMemberSelector(selectedIDs, context.graph()));
51870
51871             if (selection$$1.empty()) {
51872                 // Return to browse mode if selected DOM elements have
51873                 // disappeared because the user moved them out of view..
51874                 var source = event && event.type === 'zoom' && event.sourceEvent;
51875                 if (drawn && source && (source.type === 'mousemove' || source.type === 'touchmove')) {
51876                     context.enter(modeBrowse$$1(context));
51877                 }
51878             } else {
51879                 selection$$1
51880                     .classed('selected', true);
51881             }
51882         }
51883
51884
51885         function esc() {
51886             if (!context.inIntro()) {
51887                 context.enter(modeBrowse$$1(context));
51888             }
51889         }
51890
51891
51892         function firstVertex() {
51893             event.preventDefault();
51894             var parent = singularParent();
51895             if (parent) {
51896                 var way = context.entity(parent);
51897                 context.enter(
51898                     modeSelect(context, [way.first()]).follow(true)
51899                 );
51900             }
51901         }
51902
51903
51904         function lastVertex() {
51905             event.preventDefault();
51906             var parent = singularParent();
51907             if (parent) {
51908                 var way = context.entity(parent);
51909                 context.enter(
51910                     modeSelect(context, [way.last()]).follow(true)
51911                 );
51912             }
51913         }
51914
51915
51916         function previousVertex() {
51917             event.preventDefault();
51918             var parent = singularParent();
51919             if (!parent) return;
51920
51921             var way = context.entity(parent),
51922                 length = way.nodes.length,
51923                 curr = way.nodes.indexOf(selectedIDs[0]),
51924                 index = -1;
51925
51926             if (curr > 0) {
51927                 index = curr - 1;
51928             } else if (way.isClosed()) {
51929                 index = length - 2;
51930             }
51931
51932             if (index !== -1) {
51933                 context.enter(
51934                     modeSelect(context, [way.nodes[index]]).follow(true)
51935                 );
51936             }
51937         }
51938
51939
51940         function nextVertex() {
51941             event.preventDefault();
51942             var parent = singularParent();
51943             if (!parent) return;
51944
51945             var way = context.entity(parent),
51946                 length = way.nodes.length,
51947                 curr = way.nodes.indexOf(selectedIDs[0]),
51948                 index = -1;
51949
51950             if (curr < length - 1) {
51951                 index = curr + 1;
51952             } else if (way.isClosed()) {
51953                 index = 0;
51954             }
51955
51956             if (index !== -1) {
51957                 context.enter(
51958                     modeSelect(context, [way.nodes[index]]).follow(true)
51959                 );
51960             }
51961         }
51962
51963
51964         function nextParent() {
51965             event.preventDefault();
51966             var parents = lodash.uniq(commonParents());
51967             if (!parents || parents.length < 2) return;
51968
51969             var index = parents.indexOf(relatedParent);
51970             if (index < 0 || index > parents.length - 2) {
51971                 relatedParent = parents[0];
51972             } else {
51973                 relatedParent = parents[index + 1];
51974             }
51975
51976             var surface = context.surface();
51977             surface.selectAll('.related')
51978                 .classed('related', false);
51979
51980             if (relatedParent) {
51981                 surface.selectAll(utilEntitySelector([relatedParent]))
51982                     .classed('related', true);
51983             }
51984         }
51985
51986
51987         behaviors.forEach(function(behavior) {
51988             context.install(behavior);
51989         });
51990
51991         var operations = lodash.without(values(Operations), operationDelete)
51992                 .map(function(o) { return o(selectedIDs, context); })
51993                 .filter(function(o) { return o.available(); });
51994
51995         operations.unshift(operationDelete(selectedIDs, context));
51996
51997         keybinding
51998             .on(['[','pgup'], previousVertex)
51999             .on([']', 'pgdown'], nextVertex)
52000             .on([uiCmd('⌘['), 'home'], firstVertex)
52001             .on([uiCmd('⌘]'), 'end'], lastVertex)
52002             .on(['\\', 'pause'], nextParent)
52003             .on('⎋', esc, true)
52004             .on('space', toggleMenu);
52005
52006         operations.forEach(function(operation) {
52007             operation.keys.forEach(function(key) {
52008                 keybinding.on(key, function() {
52009                     if (!(context.inIntro() || operation.disabled())) {
52010                         operation();
52011                     }
52012                 });
52013             });
52014         });
52015
52016         select(document)
52017             .call(keybinding);
52018
52019         radialMenu = uiRadialMenu(context, operations);
52020
52021         context.ui().sidebar
52022             .select(singular() ? singular().id : null, newFeature);
52023
52024         context.history()
52025             .on('undone.select', update)
52026             .on('redone.select', update);
52027
52028         context.map()
52029             .on('move.select', closeMenu)
52030             .on('drawn.select', selectElements);
52031
52032         selectElements();
52033
52034         var show = event && !suppressMenu;
52035
52036         if (show) {
52037             positionMenu();
52038         }
52039
52040         if (follow) {
52041             var extent$$1 = geoExtent$$1(),
52042                 graph = context.graph();
52043             selectedIDs.forEach(function(id) {
52044                 var entity = context.entity(id);
52045                 extent$$1._extend(entity.extent(graph));
52046             });
52047
52048             var loc = extent$$1.center();
52049             context.map().centerEase(loc);
52050         }
52051
52052         timeout$$1 = window.setTimeout(function() {
52053             if (show) {
52054                 showMenu();
52055             }
52056
52057             context.surface()
52058                 .on('dblclick.select', dblclick);
52059         }, 200);
52060
52061         if (selectedIDs.length > 1) {
52062             var entities = uiSelectionList(context, selectedIDs);
52063             context.ui().sidebar.show(entities);
52064         }
52065     };
52066
52067
52068     mode.exit = function() {
52069         if (timeout$$1) window.clearTimeout(timeout$$1);
52070
52071         if (inspector) wrap.call(inspector.close);
52072
52073         behaviors.forEach(function(behavior) {
52074             context.uninstall(behavior);
52075         });
52076
52077         keybinding.off();
52078         closeMenu();
52079         radialMenu = undefined;
52080
52081         context.history()
52082             .on('undone.select', null)
52083             .on('redone.select', null);
52084
52085         var surface = context.surface();
52086
52087         surface
52088             .on('dblclick.select', null);
52089
52090         surface
52091             .selectAll('.selected')
52092             .classed('selected', false);
52093
52094         surface
52095             .selectAll('.related')
52096             .classed('related', false);
52097
52098         context.map().on('drawn.select', null);
52099         context.ui().sidebar.hide();
52100     };
52101
52102
52103     return mode;
52104 }
52105
52106 function uiAccount(context) {
52107     var connection = context.connection();
52108
52109
52110     function update(selection$$1) {
52111         if (!connection.authenticated()) {
52112             selection$$1.selectAll('#userLink, #logoutLink')
52113                 .classed('hide', true);
52114             return;
52115         }
52116
52117         connection.userDetails(function(err, details) {
52118             var userLink = selection$$1.select('#userLink'),
52119                 logoutLink = selection$$1.select('#logoutLink');
52120
52121             userLink.html('');
52122             logoutLink.html('');
52123
52124             if (err) return;
52125
52126             selection$$1.selectAll('#userLink, #logoutLink')
52127                 .classed('hide', false);
52128
52129             // Link
52130             userLink.append('a')
52131                 .attr('href', connection.userURL(details.display_name))
52132                 .attr('target', '_blank');
52133
52134             // Add thumbnail or dont
52135             if (details.image_url) {
52136                 userLink.append('img')
52137                     .attr('class', 'icon pre-text user-icon')
52138                     .attr('src', details.image_url);
52139             } else {
52140                 userLink
52141                     .call(svgIcon('#icon-avatar', 'pre-text light'));
52142             }
52143
52144             // Add user name
52145             userLink.append('span')
52146                 .attr('class', 'label')
52147                 .text(details.display_name);
52148
52149             logoutLink.append('a')
52150                 .attr('class', 'logout')
52151                 .attr('href', '#')
52152                 .text(t('logout'))
52153                 .on('click.logout', function() {
52154                     event.preventDefault();
52155                     connection.logout();
52156                 });
52157         });
52158     }
52159
52160
52161     return function(selection$$1) {
52162         selection$$1.append('li')
52163             .attr('id', 'logoutLink')
52164             .classed('hide', true);
52165
52166         selection$$1.append('li')
52167             .attr('id', 'userLink')
52168             .classed('hide', true);
52169
52170         connection
52171             .on('change.account', function() { update(selection$$1); });
52172
52173         update(selection$$1);
52174     };
52175 }
52176
52177 function uiAttribution(context) {
52178     var selection$$1;
52179
52180
52181     function attribution(data, klass) {
52182         var div = selection$$1.selectAll('.' + klass)
52183             .data([0]);
52184
52185         div = div.enter()
52186             .append('div')
52187             .attr('class', klass)
52188             .merge(div);
52189
52190
52191         var background = div.selectAll('.attribution')
52192             .data(data, function(d) { return d.name(); });
52193
52194         background.exit()
52195             .remove();
52196
52197         background = background.enter()
52198             .append('span')
52199             .attr('class', 'attribution')
52200             .each(function(d) {
52201                 if (d.terms_html) {
52202                     select(this)
52203                         .html(d.terms_html);
52204                     return;
52205                 }
52206
52207                 var source = d.terms_text || d.id || d.name();
52208
52209                 if (d.logo) {
52210                     source = '<img class="source-image" src="' + context.imagePath(d.logo) + '">';
52211                 }
52212
52213                 if (d.terms_url) {
52214                     select(this)
52215                         .append('a')
52216                         .attr('href', d.terms_url)
52217                         .attr('target', '_blank')
52218                         .html(source);
52219                 } else {
52220                     select(this)
52221                         .text(source);
52222                 }
52223             })
52224             .merge(background);
52225
52226
52227         var copyright = background.selectAll('.copyright-notice')
52228             .data(function(d) {
52229                 var notice = d.copyrightNotices(context.map().zoom(), context.map().extent());
52230                 return notice ? [notice] : [];
52231             });
52232
52233         copyright.exit()
52234             .remove();
52235
52236         copyright = copyright.enter()
52237             .append('span')
52238             .attr('class', 'copyright-notice')
52239             .merge(copyright);
52240
52241         copyright
52242             .text(String);
52243     }
52244
52245
52246     function update() {
52247         attribution([context.background().baseLayerSource()], 'base-layer-attribution');
52248         attribution(context.background().overlayLayerSources().filter(function (s) {
52249             return s.validZoom(context.map().zoom());
52250         }), 'overlay-layer-attribution');
52251     }
52252
52253
52254     return function(select$$1) {
52255         selection$$1 = select$$1;
52256
52257         context.background()
52258             .on('change.attribution', update);
52259
52260         context.map()
52261             .on('move.attribution', lodash.throttle(update, 400, {leading: false}));
52262
52263         update();
52264     };
52265 }
52266
52267 function rendererBackgroundSource(data) {
52268     var source = lodash.clone(data),
52269         offset = [0, 0],
52270         name = source.name,
52271         best = !!source.best;
52272
52273     source.scaleExtent = data.scaleExtent || [0, 20];
52274     source.overzoom = data.overzoom !== false;
52275
52276
52277     source.offset = function(_) {
52278         if (!arguments.length) return offset;
52279         offset = _;
52280         return source;
52281     };
52282
52283
52284     source.nudge = function(_, zoomlevel) {
52285         offset[0] += _[0] / Math.pow(2, zoomlevel);
52286         offset[1] += _[1] / Math.pow(2, zoomlevel);
52287         return source;
52288     };
52289
52290
52291     source.name = function() {
52292         return name;
52293     };
52294
52295
52296     source.best = function() {
52297         return best;
52298     };
52299
52300
52301     source.area = function() {
52302         if (!data.polygon) return Number.MAX_VALUE;  // worldwide
52303         var area$$1 = area$1({ type: 'MultiPolygon', coordinates: [ data.polygon ] });
52304         return isNaN(area$$1) ? 0 : area$$1;
52305     };
52306
52307
52308     source.imageryUsed = function() {
52309         return source.id || name;
52310     };
52311
52312
52313     source.url = function(coord) {
52314         return data.template
52315             .replace('{x}', coord[0])
52316             .replace('{y}', coord[1])
52317             // TMS-flipped y coordinate
52318             .replace(/\{[t-]y\}/, Math.pow(2, coord[2]) - coord[1] - 1)
52319             .replace(/\{z(oom)?\}/, coord[2])
52320             .replace(/\{switch:([^}]+)\}/, function(s, r) {
52321                 var subdomains = r.split(',');
52322                 return subdomains[(coord[0] + coord[1]) % subdomains.length];
52323             })
52324             .replace('{u}', function() {
52325                 var u = '';
52326                 for (var zoom$$1 = coord[2]; zoom$$1 > 0; zoom$$1--) {
52327                     var b = 0;
52328                     var mask = 1 << (zoom$$1 - 1);
52329                     if ((coord[0] & mask) !== 0) b++;
52330                     if ((coord[1] & mask) !== 0) b += 2;
52331                     u += b.toString();
52332                 }
52333                 return u;
52334             });
52335     };
52336
52337
52338     source.intersects = function(extent$$1) {
52339         extent$$1 = extent$$1.polygon();
52340         return !data.polygon || data.polygon.some(function(polygon) {
52341             return geoPolygonIntersectsPolygon(polygon, extent$$1, true);
52342         });
52343     };
52344
52345
52346     source.validZoom = function(z) {
52347         return source.scaleExtent[0] <= z &&
52348             (source.overzoom || source.scaleExtent[1] > z);
52349     };
52350
52351
52352     source.isLocatorOverlay = function() {
52353         return name === 'Locator Overlay';
52354     };
52355
52356
52357     source.copyrightNotices = function() {};
52358
52359
52360     return source;
52361 }
52362
52363
52364 rendererBackgroundSource.Bing = function(data, dispatch$$1) {
52365     // http://msdn.microsoft.com/en-us/library/ff701716.aspx
52366     // http://msdn.microsoft.com/en-us/library/ff701701.aspx
52367
52368     data.template = 'https://ecn.t{switch:0,1,2,3}.tiles.virtualearth.net/tiles/a{u}.jpeg?g=587&mkt=en-gb&n=z';
52369
52370     var bing = rendererBackgroundSource(data),
52371         key = 'Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU', // Same as P2 and JOSM
52372         url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial?include=ImageryProviders&key=' +
52373             key + '&jsonp={callback}',
52374         providers = [];
52375
52376     jsonpRequest(url, function(json$$1) {
52377         providers = json$$1.resourceSets[0].resources[0].imageryProviders.map(function(provider) {
52378             return {
52379                 attribution: provider.attribution,
52380                 areas: provider.coverageAreas.map(function(area$$1) {
52381                     return {
52382                         zoom: [area$$1.zoomMin, area$$1.zoomMax],
52383                         extent: geoExtent$$1([area$$1.bbox[1], area$$1.bbox[0]], [area$$1.bbox[3], area$$1.bbox[2]])
52384                     };
52385                 })
52386             };
52387         });
52388         dispatch$$1.call('change');
52389     });
52390
52391     bing.copyrightNotices = function(zoom$$1, extent$$1) {
52392         zoom$$1 = Math.min(zoom$$1, 21);
52393         return providers.filter(function(provider) {
52394             return lodash.some(provider.areas, function(area$$1) {
52395                 return extent$$1.intersects(area$$1.extent) &&
52396                     area$$1.zoom[0] <= zoom$$1 &&
52397                     area$$1.zoom[1] >= zoom$$1;
52398             });
52399         }).map(function(provider) {
52400             return provider.attribution;
52401         }).join(', ');
52402     };
52403
52404     bing.logo = 'bing_maps.png';
52405     bing.terms_url = 'https://blog.openstreetmap.org/2010/11/30/microsoft-imagery-details';
52406
52407     return bing;
52408 };
52409
52410
52411 rendererBackgroundSource.None = function() {
52412     var source = rendererBackgroundSource({ id: 'none', template: '' });
52413
52414     source.name = function() {
52415         return t('background.none');
52416     };
52417
52418     source.imageryUsed = function() {
52419         return 'None';
52420     };
52421
52422     source.area = function() {
52423         return -1;  // sources in background pane are sorted by area
52424     };
52425
52426     return source;
52427 };
52428
52429
52430 rendererBackgroundSource.Custom = function(template) {
52431     var source = rendererBackgroundSource({ id: 'custom', template: template });
52432
52433     source.name = function() {
52434         return t('background.custom');
52435     };
52436
52437     source.imageryUsed = function() {
52438         return 'Custom (' + template + ')';
52439     };
52440
52441     source.area = function() {
52442         return -2;  // sources in background pane are sorted by area
52443     };
52444
52445     return source;
52446 };
52447
52448 function rendererTileLayer(context) {
52449     var tileSize = 256,
52450         tile = d3geoTile(),
52451         projection,
52452         cache = {},
52453         tileOrigin,
52454         z,
52455         transformProp = utilPrefixCSSProperty('Transform'),
52456         source = rendererBackgroundSource.None();
52457
52458
52459     // blacklist overlay tiles around Null Island..
52460     function nearNullIsland(x, y, z) {
52461         if (z >= 7) {
52462             var center = Math.pow(2, z - 1),
52463                 width = Math.pow(2, z - 6),
52464                 min$$1 = center - (width / 2),
52465                 max$$1 = center + (width / 2) - 1;
52466             return x >= min$$1 && x <= max$$1 && y >= min$$1 && y <= max$$1;
52467         }
52468         return false;
52469     }
52470
52471
52472     function tileSizeAtZoom(d, z) {
52473         var epsilon = 0.002;
52474         return ((tileSize * Math.pow(2, z - d[2])) / tileSize) + epsilon;
52475     }
52476
52477
52478     function atZoom(t, distance) {
52479         var power = Math.pow(2, distance);
52480         return [
52481             Math.floor(t[0] * power),
52482             Math.floor(t[1] * power),
52483             t[2] + distance];
52484     }
52485
52486
52487     function lookUp(d) {
52488         for (var up = -1; up > -d[2]; up--) {
52489             var tile = atZoom(d, up);
52490             if (cache[source.url(tile)] !== false) {
52491                 return tile;
52492             }
52493         }
52494     }
52495
52496
52497     function uniqueBy(a, n) {
52498         var o = [], seen = {};
52499         for (var i = 0; i < a.length; i++) {
52500             if (seen[a[i][n]] === undefined) {
52501                 o.push(a[i]);
52502                 seen[a[i][n]] = true;
52503             }
52504         }
52505         return o;
52506     }
52507
52508
52509     function addSource(d) {
52510         d.push(source.url(d));
52511         return d;
52512     }
52513
52514
52515     // Update tiles based on current state of `projection`.
52516     function background(selection$$1) {
52517         tile.scale(projection.scale() * 2 * Math.PI)
52518             .translate(projection.translate());
52519
52520         tileOrigin = [
52521             projection.scale() * Math.PI - projection.translate()[0],
52522             projection.scale() * Math.PI - projection.translate()[1]];
52523
52524         z = Math.max(Math.log(projection.scale() * 2 * Math.PI) / Math.log(2) - 8, 0);
52525
52526         render(selection$$1);
52527     }
52528
52529
52530     // Derive the tiles onscreen, remove those offscreen and position them.
52531     // Important that this part not depend on `projection` because it's
52532     // rentered when tiles load/error (see #644).
52533     function render(selection$$1) {
52534         var requests = [];
52535         var showDebug = context.getDebug('tile') && !source.overlay;
52536
52537         if (source.validZoom(z)) {
52538             tile().forEach(function(d) {
52539                 addSource(d);
52540                 if (d[3] === '') return;
52541                 if (typeof d[3] !== 'string') return; // Workaround for chrome crash https://github.com/openstreetmap/iD/issues/2295
52542                 requests.push(d);
52543                 if (cache[d[3]] === false && lookUp(d)) {
52544                     requests.push(addSource(lookUp(d)));
52545                 }
52546             });
52547
52548             requests = uniqueBy(requests, 3).filter(function(r) {
52549                 if (!!source.overlay && nearNullIsland(r[0], r[1], r[2])) {
52550                     return false;
52551                 }
52552                 // don't re-request tiles which have failed in the past
52553                 return cache[r[3]] !== false;
52554             });
52555         }
52556
52557         var pixelOffset = [
52558             source.offset()[0] * Math.pow(2, z),
52559             source.offset()[1] * Math.pow(2, z)
52560         ];
52561
52562         function load(d) {
52563             cache[d[3]] = true;
52564             select(this)
52565                 .on('error', null)
52566                 .on('load', null)
52567                 .classed('tile-loaded', true);
52568             render(selection$$1);
52569         }
52570
52571         function error(d) {
52572             cache[d[3]] = false;
52573             select(this)
52574                 .on('error', null)
52575                 .on('load', null)
52576                 .remove();
52577             render(selection$$1);
52578         }
52579
52580         function imageTransform(d) {
52581             var _ts = tileSize * Math.pow(2, z - d[2]);
52582             var scale = tileSizeAtZoom(d, z);
52583             return 'translate(' +
52584                 ((d[0] * _ts) - tileOrigin[0] + pixelOffset[0]) + 'px,' +
52585                 ((d[1] * _ts) - tileOrigin[1] + pixelOffset[1]) + 'px)' +
52586                 'scale(' + scale + ',' + scale + ')';
52587         }
52588
52589         function debugTransform(d) {
52590             var _ts = tileSize * Math.pow(2, z - d[2]);
52591             var scale = tileSizeAtZoom(d, z);
52592             return 'translate(' +
52593                 ((d[0] * _ts) - tileOrigin[0] + pixelOffset[0] + scale * (tileSize / 4)) + 'px,' +
52594                 ((d[1] * _ts) - tileOrigin[1] + pixelOffset[1] + scale * (tileSize / 2)) + 'px)';
52595         }
52596
52597
52598         var image = selection$$1.selectAll('img')
52599             .data(requests, function(d) { return d[3]; });
52600
52601         image.exit()
52602             .style(transformProp, imageTransform)
52603             .classed('tile-removing', true)
52604             .each(function() {
52605                 var tile = select(this);
52606                 window.setTimeout(function() {
52607                     if (tile.classed('tile-removing')) {
52608                         tile.remove();
52609                     }
52610                 }, 300);
52611             });
52612
52613         image.enter()
52614           .append('img')
52615             .attr('class', 'tile')
52616             .attr('src', function(d) { return d[3]; })
52617             .on('error', error)
52618             .on('load', load)
52619           .merge(image)
52620             .style(transformProp, imageTransform)
52621             .classed('tile-debug', showDebug)
52622             .classed('tile-removing', false);
52623
52624
52625         var debug = selection$$1.selectAll('.tile-label-debug')
52626             .data(showDebug ? requests : [], function(d) { return d[3]; });
52627
52628         debug.exit()
52629             .remove();
52630
52631         debug.enter()
52632           .append('div')
52633             .attr('class', 'tile-label-debug')
52634           .merge(debug)
52635             .text(function(d) { return d[2] + ' / ' + d[0] + ' / ' + d[1]; })
52636             .style(transformProp, debugTransform);
52637     }
52638
52639
52640     background.projection = function(_) {
52641         if (!arguments.length) return projection;
52642         projection = _;
52643         return background;
52644     };
52645
52646
52647     background.dimensions = function(_) {
52648         if (!arguments.length) return tile.size();
52649         tile.size(_);
52650         return background;
52651     };
52652
52653
52654     background.source = function(_) {
52655         if (!arguments.length) return source;
52656         source = _;
52657         cache = {};
52658         tile.scaleExtent(source.scaleExtent);
52659         return background;
52660     };
52661
52662
52663     return background;
52664 }
52665
52666 function rendererBackground(context) {
52667     var dispatch$$1 = dispatch('change'),
52668         baseLayer = rendererTileLayer(context).projection(context.projection),
52669         overlayLayers = [],
52670         backgroundSources;
52671
52672
52673     function findSource(id) {
52674         return lodash.find(backgroundSources, function(d) {
52675             return d.id && d.id === id;
52676         });
52677     }
52678
52679
52680     function background(selection$$1) {
52681         var base = selection$$1.selectAll('.layer-background')
52682             .data([0]);
52683
52684         base.enter()
52685           .insert('div', '.layer-data')
52686             .attr('class', 'layer layer-background')
52687           .merge(base)
52688             .call(baseLayer);
52689
52690         var overlays = selection$$1.selectAll('.layer-overlay')
52691             .data(overlayLayers, function(d) { return d.source().name(); });
52692
52693         overlays.exit()
52694             .remove();
52695
52696         overlays.enter()
52697           .insert('div', '.layer-data')
52698             .attr('class', 'layer layer-overlay')
52699           .merge(overlays)
52700             .each(function(layer) { select(this).call(layer); });
52701     }
52702
52703
52704     background.updateImagery = function() {
52705         var b = background.baseLayerSource(),
52706             o = overlayLayers.map(function (d) { return d.source().id; }).join(','),
52707             meters = geoOffsetToMeters(b.offset()),
52708             epsilon = 0.01,
52709             x = +meters[0].toFixed(2),
52710             y = +meters[1].toFixed(2),
52711             q = utilStringQs(window.location.hash.substring(1));
52712
52713         var id = b.id;
52714         if (id === 'custom') {
52715             id = 'custom:' + b.template;
52716         }
52717
52718         if (id) {
52719             q.background = id;
52720         } else {
52721             delete q.background;
52722         }
52723
52724         if (o) {
52725             q.overlays = o;
52726         } else {
52727             delete q.overlays;
52728         }
52729
52730         if (Math.abs(x) > epsilon || Math.abs(y) > epsilon) {
52731             q.offset = x + ',' + y;
52732         } else {
52733             delete q.offset;
52734         }
52735
52736         window.location.replace('#' + utilQsString(q, true));
52737
52738         var imageryUsed = [b.imageryUsed()];
52739
52740         overlayLayers.forEach(function (d) {
52741             var source = d.source();
52742             if (!source.isLocatorOverlay()) {
52743                 imageryUsed.push(source.imageryUsed());
52744             }
52745         });
52746
52747         var gpx = context.layers().layer('gpx');
52748         if (gpx && gpx.enabled() && gpx.hasGpx()) {
52749             imageryUsed.push('Local GPX');
52750         }
52751
52752         var mapillary_images = context.layers().layer('mapillary-images');
52753         if (mapillary_images && mapillary_images.enabled()) {
52754             imageryUsed.push('Mapillary Images');
52755         }
52756
52757         var mapillary_signs = context.layers().layer('mapillary-signs');
52758         if (mapillary_signs && mapillary_signs.enabled()) {
52759             imageryUsed.push('Mapillary Signs');
52760         }
52761
52762         context.history().imageryUsed(imageryUsed);
52763     };
52764
52765
52766     background.sources = function(extent$$1) {
52767         return backgroundSources.filter(function(source) {
52768             return source.intersects(extent$$1);
52769         });
52770     };
52771
52772
52773     background.dimensions = function(_) {
52774         if (!_) return;
52775         baseLayer.dimensions(_);
52776
52777         overlayLayers.forEach(function(layer) {
52778             layer.dimensions(_);
52779         });
52780     };
52781
52782
52783     background.baseLayerSource = function(d) {
52784         if (!arguments.length) return baseLayer.source();
52785         baseLayer.source(d);
52786         dispatch$$1.call('change');
52787         background.updateImagery();
52788         return background;
52789     };
52790
52791
52792     background.bing = function() {
52793         background.baseLayerSource(findSource('Bing'));
52794     };
52795
52796
52797     background.showsLayer = function(d) {
52798         return d === baseLayer.source() ||
52799             (d.id === 'custom' && baseLayer.source().id === 'custom') ||
52800             overlayLayers.some(function(l) { return l.source() === d; });
52801     };
52802
52803
52804     background.overlayLayerSources = function() {
52805         return overlayLayers.map(function (l) { return l.source(); });
52806     };
52807
52808
52809     background.toggleOverlayLayer = function(d) {
52810         var layer;
52811
52812         for (var i = 0; i < overlayLayers.length; i++) {
52813             layer = overlayLayers[i];
52814             if (layer.source() === d) {
52815                 overlayLayers.splice(i, 1);
52816                 dispatch$$1.call('change');
52817                 background.updateImagery();
52818                 return;
52819             }
52820         }
52821
52822         layer = rendererTileLayer(context)
52823             .source(d)
52824             .projection(context.projection)
52825             .dimensions(baseLayer.dimensions());
52826
52827         overlayLayers.push(layer);
52828         dispatch$$1.call('change');
52829         background.updateImagery();
52830     };
52831
52832
52833     background.nudge = function(d, zoom$$1) {
52834         baseLayer.source().nudge(d, zoom$$1);
52835         dispatch$$1.call('change');
52836         background.updateImagery();
52837         return background;
52838     };
52839
52840
52841     background.offset = function(d) {
52842         if (!arguments.length) return baseLayer.source().offset();
52843         baseLayer.source().offset(d);
52844         dispatch$$1.call('change');
52845         background.updateImagery();
52846         return background;
52847     };
52848
52849
52850     background.init = function() {
52851         function parseMap(qmap) {
52852             if (!qmap) return false;
52853             var args = qmap.split('/').map(Number);
52854             if (args.length < 3 || args.some(isNaN)) return false;
52855             return geoExtent$$1([args[1], args[2]]);
52856         }
52857
52858         var dataImagery = data.imagery || [],
52859             q = utilStringQs(window.location.hash.substring(1)),
52860             chosen = q.background || q.layer,
52861             extent$$1 = parseMap(q.map),
52862             best;
52863
52864         backgroundSources = dataImagery.map(function(source) {
52865             if (source.type === 'bing') {
52866                 return rendererBackgroundSource.Bing(source, dispatch$$1);
52867             } else {
52868                 return rendererBackgroundSource(source);
52869             }
52870         });
52871
52872         backgroundSources.unshift(rendererBackgroundSource.None());
52873
52874         if (!chosen && extent$$1) {
52875             best = lodash.find(this.sources(extent$$1), function(s) { return s.best(); });
52876         }
52877
52878         if (chosen && chosen.indexOf('custom:') === 0) {
52879             background.baseLayerSource(rendererBackgroundSource.Custom(chosen.replace(/^custom:/, '')));
52880         } else {
52881             background.baseLayerSource(findSource(chosen) || best || findSource('Bing') || backgroundSources[1] || backgroundSources[0]);
52882         }
52883
52884         var locator = lodash.find(backgroundSources, function(d) {
52885             return d.overlay && d.default;
52886         });
52887
52888         if (locator) {
52889             background.toggleOverlayLayer(locator);
52890         }
52891
52892         var overlays = (q.overlays || '').split(',');
52893         overlays.forEach(function(overlay) {
52894             overlay = findSource(overlay);
52895             if (overlay) {
52896                 background.toggleOverlayLayer(overlay);
52897             }
52898         });
52899
52900         if (q.gpx) {
52901             var gpx = context.layers().layer('gpx');
52902             if (gpx) {
52903                 gpx.url(q.gpx);
52904             }
52905         }
52906
52907         if (q.offset) {
52908             var offset = q.offset.replace(/;/g, ',').split(',').map(function(n) {
52909                 return !isNaN(n) && n;
52910             });
52911
52912             if (offset.length === 2) {
52913                 background.offset(geoMetersToOffset(offset));
52914             }
52915         }
52916     };
52917
52918
52919     return utilRebind(background, dispatch$$1, 'on');
52920 }
52921
52922 function rendererFeatures(context) {
52923     var traffic_roads = {
52924         'motorway': true,
52925         'motorway_link': true,
52926         'trunk': true,
52927         'trunk_link': true,
52928         'primary': true,
52929         'primary_link': true,
52930         'secondary': true,
52931         'secondary_link': true,
52932         'tertiary': true,
52933         'tertiary_link': true,
52934         'residential': true,
52935         'unclassified': true,
52936         'living_street': true
52937     };
52938
52939     var service_roads = {
52940         'service': true,
52941         'road': true,
52942         'track': true
52943     };
52944
52945     var paths = {
52946         'path': true,
52947         'footway': true,
52948         'cycleway': true,
52949         'bridleway': true,
52950         'steps': true,
52951         'pedestrian': true,
52952         'corridor': true
52953     };
52954
52955     var past_futures = {
52956         'proposed': true,
52957         'construction': true,
52958         'abandoned': true,
52959         'dismantled': true,
52960         'disused': true,
52961         'razed': true,
52962         'demolished': true,
52963         'obliterated': true
52964     };
52965
52966     var dispatch$$1 = dispatch('change', 'redraw'),
52967         _cullFactor = 1,
52968         _cache = {},
52969         _features = {},
52970         _stats = {},
52971         _keys = [],
52972         _hidden = [];
52973
52974
52975     function update() {
52976         _hidden = features.hidden();
52977         dispatch$$1.call('change');
52978         dispatch$$1.call('redraw');
52979     }
52980
52981
52982     function defineFeature(k, filter, max$$1) {
52983         _keys.push(k);
52984         _features[k] = {
52985             filter: filter,
52986             enabled: true,   // whether the user wants it enabled..
52987             count: 0,
52988             currentMax: (max$$1 || Infinity),
52989             defaultMax: (max$$1 || Infinity),
52990             enable: function() { this.enabled = true; this.currentMax = this.defaultMax; },
52991             disable: function() { this.enabled = false; this.currentMax = 0; },
52992             hidden: function() { return !context.editable() || this.count > this.currentMax * _cullFactor; },
52993             autoHidden: function() { return this.hidden() && this.currentMax > 0; }
52994         };
52995     }
52996
52997
52998     defineFeature('points', function isPoint(entity, resolver, geometry) {
52999         return geometry === 'point';
53000     }, 200);
53001
53002     defineFeature('traffic_roads', function isTrafficRoad(entity) {
53003         return traffic_roads[entity.tags.highway];
53004     });
53005
53006     defineFeature('service_roads', function isServiceRoad(entity) {
53007         return service_roads[entity.tags.highway];
53008     });
53009
53010     defineFeature('paths', function isPath(entity) {
53011         return paths[entity.tags.highway];
53012     });
53013
53014     defineFeature('buildings', function isBuilding(entity) {
53015         return (
53016             !!entity.tags['building:part'] ||
53017             (!!entity.tags.building && entity.tags.building !== 'no') ||
53018             entity.tags.amenity === 'shelter' ||
53019             entity.tags.parking === 'multi-storey' ||
53020             entity.tags.parking === 'sheds' ||
53021             entity.tags.parking === 'carports' ||
53022             entity.tags.parking === 'garage_boxes'
53023         );
53024     }, 250);
53025
53026     defineFeature('landuse', function isLanduse(entity, resolver, geometry) {
53027         return geometry === 'area' &&
53028             !_features.buildings.filter(entity) &&
53029             !_features.water.filter(entity);
53030     });
53031
53032     defineFeature('boundaries', function isBoundary(entity) {
53033         return !!entity.tags.boundary;
53034     });
53035
53036     defineFeature('water', function isWater(entity) {
53037         return (
53038             !!entity.tags.waterway ||
53039             entity.tags.natural === 'water' ||
53040             entity.tags.natural === 'coastline' ||
53041             entity.tags.natural === 'bay' ||
53042             entity.tags.landuse === 'pond' ||
53043             entity.tags.landuse === 'basin' ||
53044             entity.tags.landuse === 'reservoir' ||
53045             entity.tags.landuse === 'salt_pond'
53046         );
53047     });
53048
53049     defineFeature('rail', function isRail(entity) {
53050         return (
53051             !!entity.tags.railway ||
53052             entity.tags.landuse === 'railway'
53053         ) && !(
53054             traffic_roads[entity.tags.highway] ||
53055             service_roads[entity.tags.highway] ||
53056             paths[entity.tags.highway]
53057         );
53058     });
53059
53060     defineFeature('power', function isPower(entity) {
53061         return !!entity.tags.power;
53062     });
53063
53064     // contains a past/future tag, but not in active use as a road/path/cycleway/etc..
53065     defineFeature('past_future', function isPastFuture(entity) {
53066         if (
53067             traffic_roads[entity.tags.highway] ||
53068             service_roads[entity.tags.highway] ||
53069             paths[entity.tags.highway]
53070         ) { return false; }
53071
53072         var strings = Object.keys(entity.tags);
53073
53074         for (var i = 0; i < strings.length; i++) {
53075             var s = strings[i];
53076             if (past_futures[s] || past_futures[entity.tags[s]]) { return true; }
53077         }
53078         return false;
53079     });
53080
53081     // Lines or areas that don't match another feature filter.
53082     // IMPORTANT: The 'others' feature must be the last one defined,
53083     //   so that code in getMatches can skip this test if `hasMatch = true`
53084     defineFeature('others', function isOther(entity, resolver, geometry) {
53085         return (geometry === 'line' || geometry === 'area');
53086     });
53087
53088
53089     function features() {}
53090
53091
53092     features.features = function() {
53093         return _features;
53094     };
53095
53096
53097     features.keys = function() {
53098         return _keys;
53099     };
53100
53101
53102     features.enabled = function(k) {
53103         if (!arguments.length) {
53104             return _keys.filter(function(k) { return _features[k].enabled; });
53105         }
53106         return _features[k] && _features[k].enabled;
53107     };
53108
53109
53110     features.disabled = function(k) {
53111         if (!arguments.length) {
53112             return _keys.filter(function(k) { return !_features[k].enabled; });
53113         }
53114         return _features[k] && !_features[k].enabled;
53115     };
53116
53117
53118     features.hidden = function(k) {
53119         if (!arguments.length) {
53120             return _keys.filter(function(k) { return _features[k].hidden(); });
53121         }
53122         return _features[k] && _features[k].hidden();
53123     };
53124
53125
53126     features.autoHidden = function(k) {
53127         if (!arguments.length) {
53128             return _keys.filter(function(k) { return _features[k].autoHidden(); });
53129         }
53130         return _features[k] && _features[k].autoHidden();
53131     };
53132
53133
53134     features.enable = function(k) {
53135         if (_features[k] && !_features[k].enabled) {
53136             _features[k].enable();
53137             update();
53138         }
53139     };
53140
53141
53142     features.disable = function(k) {
53143         if (_features[k] && _features[k].enabled) {
53144             _features[k].disable();
53145             update();
53146         }
53147     };
53148
53149
53150     features.toggle = function(k) {
53151         if (_features[k]) {
53152             (function(f) { return f.enabled ? f.disable() : f.enable(); }(_features[k]));
53153             update();
53154         }
53155     };
53156
53157
53158     features.resetStats = function() {
53159         for (var i = 0; i < _keys.length; i++) {
53160             _features[_keys[i]].count = 0;
53161         }
53162         dispatch$$1.call('change');
53163     };
53164
53165
53166     features.gatherStats = function(d, resolver, dimensions) {
53167         var needsRedraw = false,
53168             type = lodash.groupBy(d, function(ent) { return ent.type; }),
53169             entities = [].concat(type.relation || [], type.way || [], type.node || []),
53170             currHidden, geometry, matches, i, j;
53171
53172         for (i = 0; i < _keys.length; i++) {
53173             _features[_keys[i]].count = 0;
53174         }
53175
53176         // adjust the threshold for point/building culling based on viewport size..
53177         // a _cullFactor of 1 corresponds to a 1000x1000px viewport..
53178         _cullFactor = dimensions[0] * dimensions[1] / 1000000;
53179
53180         for (i = 0; i < entities.length; i++) {
53181             geometry = entities[i].geometry(resolver);
53182             if (!(geometry === 'vertex' || geometry === 'relation')) {
53183                 matches = Object.keys(features.getMatches(entities[i], resolver, geometry));
53184                 for (j = 0; j < matches.length; j++) {
53185                     _features[matches[j]].count++;
53186                 }
53187             }
53188         }
53189
53190         currHidden = features.hidden();
53191         if (currHidden !== _hidden) {
53192             _hidden = currHidden;
53193             needsRedraw = true;
53194             dispatch$$1.call('change');
53195         }
53196
53197         return needsRedraw;
53198     };
53199
53200
53201     features.stats = function() {
53202         for (var i = 0; i < _keys.length; i++) {
53203             _stats[_keys[i]] = _features[_keys[i]].count;
53204         }
53205
53206         return _stats;
53207     };
53208
53209
53210     features.clear = function(d) {
53211         for (var i = 0; i < d.length; i++) {
53212             features.clearEntity(d[i]);
53213         }
53214     };
53215
53216
53217     features.clearEntity = function(entity) {
53218         delete _cache[osmEntity$$1.key(entity)];
53219     };
53220
53221
53222     features.reset = function() {
53223         _cache = {};
53224     };
53225
53226
53227     features.getMatches = function(entity, resolver, geometry) {
53228         if (geometry === 'vertex' || geometry === 'relation') return {};
53229
53230         var ent = osmEntity$$1.key(entity);
53231         if (!_cache[ent]) {
53232             _cache[ent] = {};
53233         }
53234
53235         if (!_cache[ent].matches) {
53236             var matches = {},
53237                 hasMatch = false;
53238
53239             for (var i = 0; i < _keys.length; i++) {
53240                 if (_keys[i] === 'others') {
53241                     if (hasMatch) continue;
53242
53243                     // Multipolygon members:
53244                     // If an entity...
53245                     //   1. is a way that hasn't matched other 'interesting' feature rules,
53246                     //   2. and it belongs to a single parent multipolygon relation
53247                     // ...then match whatever feature rules the parent multipolygon has matched.
53248                     // see #2548, #2887
53249                     //
53250                     // IMPORTANT:
53251                     // For this to work, getMatches must be called on relations before ways.
53252                     //
53253                     if (entity.type === 'way') {
53254                         var parents = features.getParents(entity, resolver, geometry);
53255                         if (parents.length === 1 && parents[0].isMultipolygon()) {
53256                             var pkey = osmEntity$$1.key(parents[0]);
53257                             if (_cache[pkey] && _cache[pkey].matches) {
53258                                 matches = lodash.clone(_cache[pkey].matches);
53259                                 continue;
53260                             }
53261                         }
53262                     }
53263                 }
53264
53265                 if (_features[_keys[i]].filter(entity, resolver, geometry)) {
53266                     matches[_keys[i]] = hasMatch = true;
53267                 }
53268             }
53269             _cache[ent].matches = matches;
53270         }
53271
53272         return _cache[ent].matches;
53273     };
53274
53275
53276     features.getParents = function(entity, resolver, geometry) {
53277         if (geometry === 'point') return [];
53278
53279         var ent = osmEntity$$1.key(entity);
53280         if (!_cache[ent]) {
53281             _cache[ent] = {};
53282         }
53283
53284         if (!_cache[ent].parents) {
53285             var parents = [];
53286             if (geometry === 'vertex') {
53287                 parents = resolver.parentWays(entity);
53288             } else {   // 'line', 'area', 'relation'
53289                 parents = resolver.parentRelations(entity);
53290             }
53291             _cache[ent].parents = parents;
53292         }
53293         return _cache[ent].parents;
53294     };
53295
53296
53297     features.isHiddenFeature = function(entity, resolver, geometry) {
53298         if (!_hidden.length) return false;
53299         if (!entity.version) return false;
53300
53301         var matches = features.getMatches(entity, resolver, geometry);
53302
53303         for (var i = 0; i < _hidden.length; i++) {
53304             if (matches[_hidden[i]]) return true;
53305         }
53306         return false;
53307     };
53308
53309
53310     features.isHiddenChild = function(entity, resolver, geometry) {
53311         if (!_hidden.length) return false;
53312         if (!entity.version || geometry === 'point') return false;
53313
53314         var parents = features.getParents(entity, resolver, geometry);
53315         if (!parents.length) return false;
53316
53317         for (var i = 0; i < parents.length; i++) {
53318             if (!features.isHidden(parents[i], resolver, parents[i].geometry(resolver))) {
53319                 return false;
53320             }
53321         }
53322         return true;
53323     };
53324
53325
53326     features.hasHiddenConnections = function(entity, resolver) {
53327         if (!_hidden.length) return false;
53328         var childNodes, connections;
53329
53330         if (entity.type === 'midpoint') {
53331             childNodes = [resolver.entity(entity.edge[0]), resolver.entity(entity.edge[1])];
53332             connections = [];
53333         } else {
53334             childNodes = entity.nodes ? resolver.childNodes(entity) : [];
53335             connections = features.getParents(entity, resolver, entity.geometry(resolver));
53336         }
53337
53338         // gather ways connected to child nodes..
53339         connections = lodash.reduce(childNodes, function(result, e) {
53340             return resolver.isShared(e) ? lodash.union(result, resolver.parentWays(e)) : result;
53341         }, connections);
53342
53343         return connections.length ? lodash.some(connections, function(e) {
53344             return features.isHidden(e, resolver, e.geometry(resolver));
53345         }) : false;
53346     };
53347
53348
53349     features.isHidden = function(entity, resolver, geometry) {
53350         if (!_hidden.length) return false;
53351         if (!entity.version) return false;
53352
53353         var fn = (geometry === 'vertex' ? features.isHiddenChild : features.isHiddenFeature);
53354         return fn(entity, resolver, geometry);
53355     };
53356
53357
53358     features.filter = function(d, resolver) {
53359         if (!_hidden.length) return d;
53360
53361         var result = [];
53362         for (var i = 0; i < d.length; i++) {
53363             var entity = d[i];
53364             if (!features.isHidden(entity, resolver, entity.geometry(resolver))) {
53365                 result.push(entity);
53366             }
53367         }
53368         return result;
53369     };
53370
53371
53372     return utilRebind(features, dispatch$$1, 'on');
53373 }
53374
53375 function utilBindOnce(target, type, listener, capture) {
53376     var typeOnce = type + '.once';
53377     function one() {
53378         target.on(typeOnce, null);
53379         listener.apply(this, arguments);
53380     }
53381     target.on(typeOnce, one, capture);
53382     return this;
53383 }
53384
53385 function rendererMap(context) {
53386
53387     var dimensions = [1, 1],
53388         dispatch$$1 = dispatch('move', 'drawn'),
53389         projection = context.projection,
53390         dblclickEnabled = true,
53391         redrawEnabled = true,
53392         transformStart = projection.transform(),
53393         transformed = false,
53394         minzoom = 0,
53395         drawLayers = svgLayers(projection, context),
53396         drawPoints = svgPoints$$1(projection, context),
53397         drawVertices = svgVertices$$1(projection, context),
53398         drawLines = svgLines$$1(projection),
53399         drawAreas = svgAreas$$1(projection, context),
53400         drawMidpoints = svgMidpoints$$1(projection, context),
53401         drawLabels = svgLabels(projection, context),
53402         supersurface,
53403         wrapper,
53404         surface,
53405         mouse$$1,
53406         mousemove;
53407
53408     var zoom$$1 = zoom()
53409             .scaleExtent([ztok(2), ztok(24)])   // TODO: uncomment interpolate when d3.zoom 1.0.4 avail:
53410             // .interpolate(d3.interpolate)     // https://github.com/d3/d3-zoom/issues/54
53411             .on('zoom', zoomPan);               // default zoom interpolator does a fly-out-in
53412
53413     var _selection = select(null);
53414
53415
53416     function map$$1(selection$$1) {
53417
53418         _selection = selection$$1;
53419
53420         context
53421             .on('change.map', immediateRedraw);
53422         context.connection()
53423             .on('change.map', immediateRedraw);
53424         context.history()
53425             .on('change.map', immediateRedraw);
53426         context.background()
53427             .on('change.map', immediateRedraw);
53428         context.features()
53429             .on('redraw.map', immediateRedraw);
53430         drawLayers
53431             .on('change.map', function() {
53432                 context.background().updateImagery();
53433                 immediateRedraw();
53434             });
53435
53436         selection$$1
53437             .on('dblclick.map', dblClick)
53438             .call(zoom$$1, projection.transform());
53439
53440         supersurface = selection$$1.append('div')
53441             .attr('id', 'supersurface')
53442             .call(utilSetTransform, 0, 0);
53443
53444         // Need a wrapper div because Opera can't cope with an absolutely positioned
53445         // SVG element: http://bl.ocks.org/jfirebaugh/6fbfbd922552bf776c16
53446         wrapper = supersurface
53447             .append('div')
53448             .attr('class', 'layer layer-data');
53449
53450         map$$1.surface = surface = wrapper
53451             .call(drawLayers)
53452             .selectAll('.surface')
53453             .attr('id', 'surface');
53454
53455         surface
53456             .call(drawLabels.observe)
53457             .on('mousedown.zoom', function() {
53458                 if (event.button === 2) {
53459                     event.stopPropagation();
53460                 }
53461             }, true)
53462             .on('mouseup.zoom', function() {
53463                 if (resetTransform()) immediateRedraw();
53464             })
53465             .on('mousemove.map', function() {
53466                 mousemove = event;
53467             })
53468             .on('mouseover.vertices', function() {
53469                 if (map$$1.editable() && !transformed) {
53470                     var hover = event.target.__data__;
53471                     surface.selectAll('.data-layer-osm')
53472                         .call(drawVertices.drawHover, context.graph(), hover, map$$1.extent(), map$$1.zoom());
53473                     dispatch$$1.call('drawn', this, {full: false});
53474                 }
53475             })
53476             .on('mouseout.vertices', function() {
53477                 if (map$$1.editable() && !transformed) {
53478                     var hover = event.relatedTarget && event.relatedTarget.__data__;
53479                     surface.selectAll('.data-layer-osm')
53480                         .call(drawVertices.drawHover, context.graph(), hover, map$$1.extent(), map$$1.zoom());
53481                     dispatch$$1.call('drawn', this, {full: false});
53482                 }
53483             });
53484
53485         supersurface
53486             .call(context.background());
53487
53488         context.on('enter.map', function() {
53489             if (map$$1.editable() && !transformed) {
53490                 var all = context.intersects(map$$1.extent()),
53491                     filter = utilFunctor(true),
53492                     graph = context.graph();
53493
53494                 all = context.features().filter(all, graph);
53495                 surface.selectAll('.data-layer-osm')
53496                     .call(drawVertices, graph, all, filter, map$$1.extent(), map$$1.zoom())
53497                     .call(drawMidpoints, graph, all, filter, map$$1.trimmedExtent());
53498                 dispatch$$1.call('drawn', this, {full: false});
53499             }
53500         });
53501
53502         map$$1.dimensions(utilGetDimensions(selection$$1));
53503
53504     }
53505
53506
53507     function ztok(z) {
53508         return 256 * Math.pow(2, z);
53509     }
53510
53511     function ktoz(k) {
53512         return Math.max(Math.log(k) / Math.LN2 - 8, 0);
53513     }
53514
53515     function pxCenter() {
53516         return [dimensions[0] / 2, dimensions[1] / 2];
53517     }
53518
53519
53520     function drawVector(difference, extent$$1) {
53521         var graph = context.graph(),
53522             features = context.features(),
53523             all = context.intersects(map$$1.extent()),
53524             data, filter;
53525
53526         if (difference) {
53527             var complete = difference.complete(map$$1.extent());
53528             data = lodash.compact(lodash.values(complete));
53529             filter = function(d) { return d.id in complete; };
53530             features.clear(data);
53531
53532         } else {
53533             // force a full redraw if gatherStats detects that a feature
53534             // should be auto-hidden (e.g. points or buildings)..
53535             if (features.gatherStats(all, graph, dimensions)) {
53536                 extent$$1 = undefined;
53537             }
53538
53539             if (extent$$1) {
53540                 data = context.intersects(map$$1.extent().intersection(extent$$1));
53541                 var set$$1 = set(lodash.map(data, 'id'));
53542                 filter = function(d) { return set$$1.has(d.id); };
53543
53544             } else {
53545                 data = all;
53546                 filter = utilFunctor(true);
53547             }
53548         }
53549
53550         data = features.filter(data, graph);
53551
53552         surface.selectAll('.data-layer-osm')
53553             .call(drawVertices, graph, data, filter, map$$1.extent(), map$$1.zoom())
53554             .call(drawLines, graph, data, filter)
53555             .call(drawAreas, graph, data, filter)
53556             .call(drawMidpoints, graph, data, filter, map$$1.trimmedExtent())
53557             .call(drawLabels, graph, data, filter, dimensions, !difference && !extent$$1)
53558             .call(drawPoints, graph, data, filter);
53559
53560         dispatch$$1.call('drawn', this, {full: true});
53561     }
53562
53563
53564     function editOff() {
53565         context.features().resetStats();
53566         surface.selectAll('.layer-osm *').remove();
53567         dispatch$$1.call('drawn', this, {full: true});
53568     }
53569
53570
53571     function dblClick() {
53572         if (!dblclickEnabled) {
53573             event.preventDefault();
53574             event.stopImmediatePropagation();
53575         }
53576     }
53577
53578
53579     function zoomPan(manualEvent) {
53580         var eventTransform = (manualEvent || event).transform;
53581
53582         if (transformStart.x === eventTransform.x &&
53583             transformStart.y === eventTransform.y &&
53584             transformStart.k === eventTransform.k) {
53585             return;  // no change
53586         }
53587
53588         if (ktoz(eventTransform.k * 2 * Math.PI) < minzoom) {
53589             surface.interrupt();
53590             uiFlash(context.container())
53591                 .select('.content')
53592                 .text(t('cannot_zoom'));
53593             setZoom(context.minEditableZoom(), true);
53594             queueRedraw();
53595             dispatch$$1.call('move', this, map$$1);
53596             return;
53597         }
53598
53599         projection.transform(eventTransform);
53600
53601         var scale = eventTransform.k / transformStart.k,
53602             tX = (eventTransform.x / scale - transformStart.x) * scale,
53603             tY = (eventTransform.y / scale - transformStart.y) * scale;
53604
53605         transformed = true;
53606         utilSetTransform(supersurface, tX, tY, scale);
53607         queueRedraw();
53608
53609         dispatch$$1.call('move', this, map$$1);
53610     }
53611
53612
53613     function resetTransform() {
53614         if (!transformed) return false;
53615
53616         surface.selectAll('.radial-menu').interrupt().remove();
53617         utilSetTransform(supersurface, 0, 0);
53618         transformed = false;
53619         return true;
53620     }
53621
53622
53623     function redraw(difference, extent$$1) {
53624         if (!surface || !redrawEnabled) return;
53625
53626         // If we are in the middle of a zoom/pan, we can't do differenced redraws.
53627         // It would result in artifacts where differenced entities are redrawn with
53628         // one transform and unchanged entities with another.
53629         if (resetTransform()) {
53630             difference = extent$$1 = undefined;
53631         }
53632
53633         var z = String(~~map$$1.zoom());
53634         if (surface.attr('data-zoom') !== z) {
53635             surface.attr('data-zoom', z)
53636                 .classed('low-zoom', z <= 16);
53637         }
53638
53639         if (!difference) {
53640             supersurface.call(context.background());
53641         }
53642
53643         wrapper
53644             .call(drawLayers);
53645
53646         // OSM
53647         if (map$$1.editable()) {
53648             context.loadTiles(projection, dimensions);
53649             drawVector(difference, extent$$1);
53650         } else {
53651             editOff();
53652         }
53653
53654         transformStart = projection.transform();
53655
53656         return map$$1;
53657     }
53658
53659
53660     var queueRedraw = lodash.throttle(redraw, 750);
53661
53662
53663     var immediateRedraw = function(difference, extent$$1) {
53664         if (!difference && !extent$$1) queueRedraw.cancel();
53665         redraw(difference, extent$$1);
53666     };
53667
53668
53669     function pointLocation(p) {
53670         var translate = projection.translate(),
53671             scale = projection.scale() * 2 * Math.PI;
53672         return [(p[0] - translate[0]) / scale, (p[1] - translate[1]) / scale];
53673     }
53674
53675
53676     function locationPoint(l) {
53677         var translate = projection.translate(),
53678             scale = projection.scale() * 2 * Math.PI;
53679         return [l[0] * scale + translate[0], l[1] * scale + translate[1]];
53680     }
53681
53682
53683     map$$1.mouse = function() {
53684         var e = mousemove || event, s;
53685         while ((s = e.sourceEvent)) e = s;
53686         return mouse$$1(e);
53687     };
53688
53689
53690     map$$1.mouseCoordinates = function() {
53691         return projection.invert(map$$1.mouse());
53692     };
53693
53694
53695     map$$1.dblclickEnable = function(_) {
53696         if (!arguments.length) return dblclickEnabled;
53697         dblclickEnabled = _;
53698         return map$$1;
53699     };
53700
53701
53702     map$$1.redrawEnable = function(_) {
53703         if (!arguments.length) return redrawEnabled;
53704         redrawEnabled = _;
53705         return map$$1;
53706     };
53707
53708
53709     function setZoom(z2, force, duration) {
53710         if (z2 === map$$1.zoom() && !force) {
53711             return false;
53712         }
53713
53714         var k = projection.scale(),
53715             k2 = Math.max(ztok(2), Math.min(ztok(24), ztok(z2))) / (2 * Math.PI),
53716             center = pxCenter(),
53717             l = pointLocation(center);
53718
53719         projection.scale(k2);
53720
53721         var t$$1 = projection.translate();
53722         l = locationPoint(l);
53723
53724         t$$1[0] += center[0] - l[0];
53725         t$$1[1] += center[1] - l[1];
53726
53727         if (duration) {
53728             projection.scale(k);  // reset scale
53729             _selection
53730                 .transition()
53731                 .duration(duration)
53732                 .on('start', function() { map$$1.startEase(); })
53733                 .call(zoom$$1.transform, identity$6.translate(t$$1[0], t$$1[1]).scale(k2));
53734         } else {
53735             projection.translate(t$$1);
53736             transformStart = projection.transform();
53737             _selection.call(zoom$$1.transform, transformStart);
53738         }
53739
53740         return true;
53741     }
53742
53743
53744     function setCenter(loc2, duration) {
53745         var c = map$$1.center();
53746         if (loc2[0] === c[0] && loc2[1] === c[1]) {
53747             return false;
53748         }
53749
53750         var t$$1 = projection.translate(),
53751             k = projection.scale(),
53752             pxC = pxCenter(),
53753             ll = projection(loc2);
53754
53755         t$$1[0] = t$$1[0] - ll[0] + pxC[0];
53756         t$$1[1] = t$$1[1] - ll[1] + pxC[1];
53757
53758         if (duration) {
53759             _selection
53760                 .transition()
53761                 .duration(duration)
53762                 .on('start', function() { map$$1.startEase(); })
53763                 .call(zoom$$1.transform, identity$6.translate(t$$1[0], t$$1[1]).scale(k));
53764         } else {
53765             projection.translate(t$$1);
53766             transformStart = projection.transform();
53767             _selection.call(zoom$$1.transform, transformStart);
53768         }
53769
53770         return true;
53771     }
53772
53773
53774     map$$1.pan = function(delta, duration) {
53775         var t$$1 = projection.translate(),
53776             k = projection.scale();
53777
53778         t$$1[0] += delta[0];
53779         t$$1[1] += delta[1];
53780
53781         if (duration) {
53782             _selection
53783                 .transition()
53784                 .duration(duration)
53785                 .on('start', function() { map$$1.startEase(); })
53786                 .call(zoom$$1.transform, identity$6.translate(t$$1[0], t$$1[1]).scale(k));
53787         } else {
53788             projection.translate(t$$1);
53789             transformStart = projection.transform();
53790             _selection.call(zoom$$1.transform, transformStart);
53791             dispatch$$1.call('move', this, map$$1);
53792             immediateRedraw();
53793         }
53794
53795         return map$$1;
53796     };
53797
53798
53799     map$$1.dimensions = function(_) {
53800         if (!arguments.length) return dimensions;
53801         var center = map$$1.center();
53802         dimensions = _;
53803         drawLayers.dimensions(dimensions);
53804         context.background().dimensions(dimensions);
53805         projection.clipExtent([[0, 0], dimensions]);
53806         mouse$$1 = utilFastMouse(supersurface.node());
53807         setCenter(center);
53808
53809         queueRedraw();
53810         return map$$1;
53811     };
53812
53813
53814     function zoomIn(delta) {
53815         setZoom(~~map$$1.zoom() + delta, true, 250);
53816     }
53817
53818     function zoomOut(delta) {
53819         setZoom(~~map$$1.zoom() - delta, true, 250);
53820     }
53821
53822     map$$1.zoomIn = function() { zoomIn(1); };
53823     map$$1.zoomInFurther = function() { zoomIn(4); };
53824
53825     map$$1.zoomOut = function() { zoomOut(1); };
53826     map$$1.zoomOutFurther = function() { zoomOut(4); };
53827
53828
53829     map$$1.center = function(loc2) {
53830         if (!arguments.length) {
53831             return projection.invert(pxCenter());
53832         }
53833
53834         if (setCenter(loc2)) {
53835             dispatch$$1.call('move', this, map$$1);
53836         }
53837
53838         queueRedraw();
53839         return map$$1;
53840     };
53841
53842
53843     map$$1.zoom = function(z2) {
53844         if (!arguments.length) {
53845             return Math.max(ktoz(projection.scale() * 2 * Math.PI), 0);
53846         }
53847
53848         if (z2 < minzoom) {
53849             surface.interrupt();
53850             uiFlash(context.container())
53851                 .select('.content')
53852                 .text(t('cannot_zoom'));
53853             z2 = context.minEditableZoom();
53854         }
53855
53856         if (setZoom(z2)) {
53857             dispatch$$1.call('move', this, map$$1);
53858         }
53859
53860         queueRedraw();
53861         return map$$1;
53862     };
53863
53864
53865     map$$1.zoomTo = function(entity, zoomLimits) {
53866         var extent$$1 = entity.extent(context.graph());
53867         if (!isFinite(extent$$1.area())) return;
53868
53869         var z2 = map$$1.trimmedExtentZoom(extent$$1);
53870         zoomLimits = zoomLimits || [context.minEditableZoom(), 20];
53871         map$$1.centerZoom(extent$$1.center(), Math.min(Math.max(z2, zoomLimits[0]), zoomLimits[1]));
53872     };
53873
53874
53875     map$$1.centerZoom = function(loc2, z2) {
53876         var centered = setCenter(loc2),
53877             zoomed   = setZoom(z2);
53878
53879         if (centered || zoomed) {
53880             dispatch$$1.call('move', this, map$$1);
53881         }
53882
53883         queueRedraw();
53884         return map$$1;
53885     };
53886
53887
53888     map$$1.centerEase = function(loc2, duration) {
53889         duration = duration || 250;
53890         setCenter(loc2, duration);
53891         return map$$1;
53892     };
53893
53894
53895     map$$1.zoomEase = function(z2, duration) {
53896         duration = duration || 250;
53897         setZoom(z2, false, duration);
53898         return map$$1;
53899     };
53900
53901
53902     map$$1.startEase = function() {
53903         utilBindOnce(surface, 'mousedown.ease', function() {
53904             map$$1.cancelEase();
53905         });
53906         return map$$1;
53907     };
53908
53909
53910     map$$1.cancelEase = function() {
53911         _selection.interrupt();
53912         return map$$1;
53913     };
53914
53915
53916     map$$1.extent = function(_) {
53917         if (!arguments.length) {
53918             return new geoExtent$$1(projection.invert([0, dimensions[1]]),
53919                                  projection.invert([dimensions[0], 0]));
53920         } else {
53921             var extent$$1 = geoExtent$$1(_);
53922             map$$1.centerZoom(extent$$1.center(), map$$1.extentZoom(extent$$1));
53923         }
53924     };
53925
53926
53927     map$$1.trimmedExtent = function(_) {
53928         if (!arguments.length) {
53929             var headerY = 60, footerY = 30, pad = 10;
53930             return new geoExtent$$1(projection.invert([pad, dimensions[1] - footerY - pad]),
53931                                  projection.invert([dimensions[0] - pad, headerY + pad]));
53932         } else {
53933             var extent$$1 = geoExtent$$1(_);
53934             map$$1.centerZoom(extent$$1.center(), map$$1.trimmedExtentZoom(extent$$1));
53935         }
53936     };
53937
53938
53939     function calcZoom(extent$$1, dim) {
53940         var tl = projection([extent$$1[0][0], extent$$1[1][1]]),
53941             br = projection([extent$$1[1][0], extent$$1[0][1]]);
53942
53943         // Calculate maximum zoom that fits extent
53944         var hFactor = (br[0] - tl[0]) / dim[0],
53945             vFactor = (br[1] - tl[1]) / dim[1],
53946             hZoomDiff = Math.log(Math.abs(hFactor)) / Math.LN2,
53947             vZoomDiff = Math.log(Math.abs(vFactor)) / Math.LN2,
53948             newZoom = map$$1.zoom() - Math.max(hZoomDiff, vZoomDiff);
53949
53950         return newZoom;
53951     }
53952
53953
53954     map$$1.extentZoom = function(_) {
53955         return calcZoom(geoExtent$$1(_), dimensions);
53956     };
53957
53958
53959     map$$1.trimmedExtentZoom = function(_) {
53960         var trimY = 120, trimX = 40,
53961             trimmed = [dimensions[0] - trimX, dimensions[1] - trimY];
53962         return calcZoom(geoExtent$$1(_), trimmed);
53963     };
53964
53965
53966     map$$1.editable = function() {
53967         return map$$1.zoom() >= context.minEditableZoom();
53968     };
53969
53970
53971     map$$1.minzoom = function(_) {
53972         if (!arguments.length) return minzoom;
53973         minzoom = _;
53974         return map$$1;
53975     };
53976
53977
53978     map$$1.layers = drawLayers;
53979
53980
53981     return utilRebind(map$$1, dispatch$$1, 'on');
53982 }
53983
53984 var TAU = 2 * Math.PI;
53985 function ztok(z) { return 256 * Math.pow(2, z) / TAU; }
53986 function ktoz(k) { return Math.log(k * TAU) / Math.LN2 - 8; }
53987 function vecSub(a, b) { return [ a[0] - b[0], a[1] - b[1] ]; }
53988 function vecScale(a, b) { return [ a[0] * b, a[1] * b ]; }
53989
53990
53991 function uiMapInMap(context) {
53992     var key = '/';
53993
53994
53995     function map_in_map(selection$$1) {
53996         var backgroundLayer = rendererTileLayer(context),
53997             overlayLayers = {},
53998             projection = geoRawMercator(),
53999             gpxLayer = svgGpx(projection, context).showLabels(false),
54000             debugLayer = svgDebug(projection, context),
54001             zoom$$1 = zoom()
54002                 .scaleExtent([ztok(0.5), ztok(24)])
54003                 .on('start', zoomStarted)
54004                 .on('zoom', zoomed)
54005                 .on('end', zoomEnded),
54006             isTransformed = false,
54007             isHidden = true,
54008             skipEvents = false,
54009             gesture = null,
54010             zDiff = 6,    // by default, minimap renders at (main zoom - 6)
54011             wrap = select(null),
54012             tiles = select(null),
54013             viewport = select(null),
54014             tStart,  // transform at start of gesture
54015             tCurr,   // transform at most recent event
54016             timeoutId;
54017
54018
54019         function zoomStarted() {
54020             if (skipEvents) return;
54021             tStart = tCurr = projection.transform();
54022             gesture = null;
54023         }
54024
54025
54026         function zoomed() {
54027             if (skipEvents) return;
54028
54029             var x = event.transform.x,
54030                 y = event.transform.y,
54031                 k = event.transform.k,
54032                 isZooming = (k !== tStart.k),
54033                 isPanning = (x !== tStart.x || y !== tStart.y);
54034
54035             if (!isZooming && !isPanning) {
54036                 return;  // no change
54037             }
54038
54039             // lock in either zooming or panning, don't allow both in minimap.
54040             if (!gesture) {
54041                 gesture = isZooming ? 'zoom' : 'pan';
54042             }
54043
54044             var tMini = projection.transform(),
54045                 tX, tY, scale;
54046
54047             if (gesture === 'zoom') {
54048                 var dMini = utilGetDimensions(wrap),
54049                     cMini = vecScale(dMini, 0.5);
54050                 scale = k / tMini.k;
54051                 tX = (cMini[0] / scale - cMini[0]) * scale;
54052                 tY = (cMini[1] / scale - cMini[1]) * scale;
54053             } else {
54054                 k = tMini.k;
54055                 scale = 1;
54056                 tX = x - tMini.x;
54057                 tY = y - tMini.y;
54058             }
54059
54060             utilSetTransform(tiles, tX, tY, scale);
54061             utilSetTransform(viewport, 0, 0, scale);
54062             isTransformed = true;
54063             tCurr = identity$6.translate(x, y).scale(k);
54064
54065             var zMain = ktoz(context.projection.scale()),
54066                 zMini = ktoz(k);
54067
54068             zDiff = zMain - zMini;
54069
54070             queueRedraw();
54071         }
54072
54073
54074         function zoomEnded() {
54075             if (skipEvents) return;
54076             if (gesture !== 'pan') return;
54077
54078             updateProjection();
54079             gesture = null;
54080             var dMini = utilGetDimensions(wrap),
54081                 cMini = vecScale(dMini, 0.5);
54082             context.map().center(projection.invert(cMini));   // recenter main map..
54083         }
54084
54085
54086         function updateProjection() {
54087             var loc = context.map().center(),
54088                 dMini = utilGetDimensions(wrap),
54089                 cMini = vecScale(dMini, 0.5),
54090                 tMain = context.projection.transform(),
54091                 zMain = ktoz(tMain.k),
54092                 zMini = Math.max(zMain - zDiff, 0.5),
54093                 kMini = ztok(zMini);
54094
54095             projection
54096                 .translate([tMain.x, tMain.y])
54097                 .scale(kMini);
54098
54099             var point = projection(loc),
54100                 mouse$$1 = (gesture === 'pan') ? vecSub([tCurr.x, tCurr.y], [tStart.x, tStart.y]) : [0, 0],
54101                 xMini = cMini[0] - point[0] + tMain.x + mouse$$1[0],
54102                 yMini = cMini[1] - point[1] + tMain.y + mouse$$1[1];
54103
54104             projection
54105                 .translate([xMini, yMini])
54106                 .clipExtent([[0, 0], dMini]);
54107
54108             tCurr = projection.transform();
54109
54110             if (isTransformed) {
54111                 utilSetTransform(tiles, 0, 0);
54112                 utilSetTransform(viewport, 0, 0);
54113                 isTransformed = false;
54114             }
54115
54116             zoom$$1
54117                 .scaleExtent([ztok(0.5), ztok(zMain - 3)]);
54118
54119             skipEvents = true;
54120             wrap.call(zoom$$1.transform, tCurr);
54121             skipEvents = false;
54122         }
54123
54124
54125         function redraw() {
54126             clearTimeout(timeoutId);
54127             if (isHidden) return;
54128
54129             updateProjection();
54130
54131             var dMini = utilGetDimensions(wrap),
54132                 zMini = ktoz(projection.scale());
54133
54134             // setup tile container
54135             tiles = wrap
54136                 .selectAll('.map-in-map-tiles')
54137                 .data([0]);
54138
54139             tiles = tiles.enter()
54140                 .append('div')
54141                 .attr('class', 'map-in-map-tiles')
54142                 .merge(tiles);
54143
54144             // redraw background
54145             backgroundLayer
54146                 .source(context.background().baseLayerSource())
54147                 .projection(projection)
54148                 .dimensions(dMini);
54149
54150             var background = tiles
54151                 .selectAll('.map-in-map-background')
54152                 .data([0]);
54153
54154             background.enter()
54155                 .append('div')
54156                 .attr('class', 'map-in-map-background')
54157                 .merge(background)
54158                 .call(backgroundLayer);
54159
54160
54161             // redraw overlay
54162             var overlaySources = context.background().overlayLayerSources();
54163             var activeOverlayLayers = [];
54164             for (var i = 0; i < overlaySources.length; i++) {
54165                 if (overlaySources[i].validZoom(zMini)) {
54166                     if (!overlayLayers[i]) overlayLayers[i] = rendererTileLayer(context);
54167                     activeOverlayLayers.push(overlayLayers[i]
54168                         .source(overlaySources[i])
54169                         .projection(projection)
54170                         .dimensions(dMini));
54171                 }
54172             }
54173
54174             var overlay = tiles
54175                 .selectAll('.map-in-map-overlay')
54176                 .data([0]);
54177
54178             overlay = overlay.enter()
54179                 .append('div')
54180                 .attr('class', 'map-in-map-overlay')
54181                 .merge(overlay);
54182
54183
54184             var overlays = overlay
54185                 .selectAll('div')
54186                 .data(activeOverlayLayers, function(d) { return d.source().name(); });
54187
54188             overlays.exit()
54189                 .remove();
54190
54191             overlays = overlays.enter()
54192                 .append('div')
54193                 .merge(overlays)
54194                 .each(function(layer) { select(this).call(layer); });
54195
54196
54197             var dataLayers = tiles
54198                 .selectAll('.map-in-map-data')
54199                 .data([0]);
54200
54201             dataLayers.exit()
54202                 .remove();
54203
54204             dataLayers = dataLayers.enter()
54205                 .append('svg')
54206                 .attr('class', 'map-in-map-data')
54207                 .merge(dataLayers)
54208                 .call(gpxLayer)
54209                 .call(debugLayer);
54210
54211
54212             // redraw viewport bounding box
54213             if (gesture !== 'pan') {
54214                 var getPath = index$5(projection),
54215                     bbox = { type: 'Polygon', coordinates: [context.map().extent().polygon()] };
54216
54217                 viewport = wrap.selectAll('.map-in-map-viewport')
54218                     .data([0]);
54219
54220                 viewport = viewport.enter()
54221                     .append('svg')
54222                     .attr('class', 'map-in-map-viewport')
54223                     .merge(viewport);
54224
54225
54226                 var path$$1 = viewport.selectAll('.map-in-map-bbox')
54227                     .data([bbox]);
54228
54229                 path$$1.enter()
54230                     .append('path')
54231                     .attr('class', 'map-in-map-bbox')
54232                     .merge(path$$1)
54233                     .attr('d', getPath)
54234                     .classed('thick', function(d) { return getPath.area(d) < 30; });
54235             }
54236         }
54237
54238
54239         function queueRedraw() {
54240             clearTimeout(timeoutId);
54241             timeoutId = setTimeout(function() { redraw(); }, 750);
54242         }
54243
54244
54245         function toggle() {
54246             if (event) event.preventDefault();
54247
54248             isHidden = !isHidden;
54249
54250             var label = select('.minimap-toggle');
54251             label.classed('active', !isHidden)
54252                 .select('input').property('checked', !isHidden);
54253
54254             if (isHidden) {
54255                 wrap
54256                     .style('display', 'block')
54257                     .style('opacity', '1')
54258                     .transition()
54259                     .duration(200)
54260                     .style('opacity', '0')
54261                     .on('end', function() {
54262                         selection$$1.selectAll('.map-in-map')
54263                             .style('display', 'none');
54264                     });
54265             } else {
54266                 wrap
54267                     .style('display', 'block')
54268                     .style('opacity', '0')
54269                     .transition()
54270                     .duration(200)
54271                     .style('opacity', '1')
54272                     .on('end', function() {
54273                         redraw();
54274                     });
54275             }
54276         }
54277
54278
54279         uiMapInMap.toggle = toggle;
54280
54281         wrap = selection$$1.selectAll('.map-in-map')
54282             .data([0]);
54283
54284         wrap = wrap.enter()
54285             .append('div')
54286             .attr('class', 'map-in-map')
54287             .style('display', (isHidden ? 'none' : 'block'))
54288             .call(zoom$$1)
54289             .on('dblclick.zoom', null)
54290             .merge(wrap);
54291
54292         context.map()
54293             .on('drawn.map-in-map', function(drawn) {
54294                 if (drawn.full === true) {
54295                     redraw();
54296                 }
54297             });
54298
54299         redraw();
54300
54301         var keybinding = d3keybinding('map-in-map')
54302             .on(key, toggle);
54303
54304         select(document)
54305             .call(keybinding);
54306     }
54307
54308     return map_in_map;
54309 }
54310
54311 function uiTooltipHtml(text, key) {
54312     var s = '<span>' + text + '</span>';
54313     if (key) {
54314         s += '<div class="keyhint-wrap">' +
54315             '<span> ' + (t('tooltip_keyhint')) + ' </span>' +
54316             '<span class="keyhint"> ' + key + '</span></div>';
54317     }
54318     return s;
54319 }
54320
54321 function uiBackground(context) {
54322     var key = 'B',
54323         detected = utilDetect(),
54324         opacities = [1, 0.75, 0.5, 0.25],
54325         directions = [
54326             ['right', [0.5, 0]],
54327             ['top', [0, -0.5]],
54328             ['left', [-0.5, 0]],
54329             ['bottom', [0, 0.5]]],
54330         opacityDefault = (context.storage('background-opacity') !== null) ?
54331             (+context.storage('background-opacity')) : 1.0,
54332         customTemplate = context.storage('background-custom-template') || '',
54333         previous;
54334
54335     // Can be 0 from <1.3.0 use or due to issue #1923.
54336     if (opacityDefault === 0) opacityDefault = 1.0;
54337
54338
54339     function background(selection$$1) {
54340
54341         function sortSources(a, b) {
54342             return a.best() && !b.best() ? -1
54343                 : b.best() && !a.best() ? 1
54344                 : descending(a.area(), b.area()) || ascending(a.name(), b.name()) || 0;
54345         }
54346
54347
54348         function setOpacity(d) {
54349             var bg = context.container().selectAll('.layer-background')
54350                 .transition()
54351                 .style('opacity', d)
54352                 .attr('data-opacity', d);
54353
54354             if (!detected.opera) {
54355                 utilSetTransform(bg, 0, 0);
54356             }
54357
54358             opacityList.selectAll('li')
54359                 .classed('active', function(_) { return _ === d; });
54360
54361             context.storage('background-opacity', d);
54362         }
54363
54364
54365         function setTooltips(selection$$1) {
54366             selection$$1.each(function(d, i, nodes) {
54367                 var item = select(this).select('label'),
54368                     placement = (i < nodes.length / 2) ? 'bottom' : 'top';
54369
54370                 if (d === previous) {
54371                     item.call(tooltip()
54372                         .placement(placement)
54373                         .html(true)
54374                         .title(function() {
54375                             var tip = '<div>' + t('background.switch') + '</div>';
54376                             return uiTooltipHtml(tip, uiCmd('⌘B'));
54377                         })
54378                     );
54379                 } else if (d.description) {
54380                     item.call(tooltip()
54381                         .placement(placement)
54382                         .title(d.description)
54383                     );
54384                 } else {
54385                     item.call(tooltip().destroy);
54386                 }
54387             });
54388         }
54389
54390
54391         function selectLayer() {
54392             function active$$1(d) {
54393                 return context.background().showsLayer(d);
54394             }
54395
54396             content.selectAll('.layer, .custom_layer')
54397                 .classed('active', active$$1)
54398                 .classed('switch', function(d) { return d === previous; })
54399                 .call(setTooltips)
54400                 .selectAll('input')
54401                 .property('checked', active$$1);
54402         }
54403
54404
54405         function clickSetSource(d) {
54406             event.preventDefault();
54407             previous = context.background().baseLayerSource();
54408             context.background().baseLayerSource(d);
54409             selectLayer();
54410             document.activeElement.blur();
54411         }
54412
54413
54414         function editCustom() {
54415             event.preventDefault();
54416             var template = window.prompt(t('background.custom_prompt'), customTemplate);
54417             if (!template ||
54418                 template.indexOf('google.com') !== -1 ||
54419                 template.indexOf('googleapis.com') !== -1 ||
54420                 template.indexOf('google.ru') !== -1) {
54421                 selectLayer();
54422                 return;
54423             }
54424             setCustom(template);
54425         }
54426
54427
54428         function setCustom(template) {
54429             context.storage('background-custom-template', template);
54430             var d = rendererBackgroundSource.Custom(template);
54431             content.selectAll('.custom_layer').datum(d);
54432             clickSetSource(d);
54433         }
54434
54435
54436         function clickSetOverlay(d) {
54437             event.preventDefault();
54438             context.background().toggleOverlayLayer(d);
54439             selectLayer();
54440             document.activeElement.blur();
54441         }
54442
54443
54444         function drawList(layerList, type, change, filter) {
54445             var sources = context.background()
54446                 .sources(context.map().extent())
54447                 .filter(filter);
54448
54449             var layerLinks = layerList.selectAll('li.layer')
54450                 .data(sources, function(d) { return d.name(); });
54451
54452             layerLinks.exit()
54453                 .remove();
54454
54455             var enter = layerLinks.enter()
54456                 .insert('li', '.custom_layer')
54457                 .attr('class', 'layer')
54458                 .classed('best', function(d) { return d.best(); });
54459
54460             enter.filter(function(d) { return d.best(); })
54461                 .append('div')
54462                 .attr('class', 'best')
54463                 .call(tooltip()
54464                     .title(t('background.best_imagery'))
54465                     .placement((textDirection === 'rtl') ? 'right' : 'left'))
54466                 .append('span')
54467                 .html('&#9733;');
54468
54469             var label = enter
54470                 .append('label');
54471
54472             label
54473                 .append('input')
54474                 .attr('type', type)
54475                 .attr('name', 'layers')
54476                 .on('change', change);
54477
54478             label
54479                 .append('span')
54480                 .text(function(d) { return d.name(); });
54481
54482
54483             layerList.selectAll('li.layer')
54484                 .sort(sortSources)
54485                 .style('display', layerList.selectAll('li.layer').data().length > 0 ? 'block' : 'none');
54486         }
54487
54488
54489         function update() {
54490             backgroundList.call(drawList, 'radio', clickSetSource, function(d) { return !d.overlay; });
54491             overlayList.call(drawList, 'checkbox', clickSetOverlay, function(d) { return d.overlay; });
54492
54493             selectLayer();
54494
54495             var source = context.background().baseLayerSource();
54496             if (source.id === 'custom') {
54497                 customTemplate = source.template;
54498             }
54499
54500             updateOffsetVal();
54501         }
54502
54503
54504         function updateOffsetVal() {
54505             var meters = geoOffsetToMeters(context.background().offset()),
54506                 x = +meters[0].toFixed(2),
54507                 y = +meters[1].toFixed(2);
54508
54509             selectAll('.nudge-inner-rect')
54510                 .select('input')
54511                 .classed('error', false)
54512                 .property('value', x + ', ' + y);
54513
54514             selectAll('.nudge-reset')
54515                 .classed('disabled', function() {
54516                     return (x === 0 && y === 0);
54517                 });
54518         }
54519
54520
54521         function resetOffset() {
54522             if (event.button !== 0) return;
54523             context.background().offset([0, 0]);
54524             updateOffsetVal();
54525         }
54526
54527
54528         function nudge(d) {
54529             context.background().nudge(d, context.map().zoom());
54530             updateOffsetVal();
54531         }
54532
54533
54534         function buttonOffset(d) {
54535             if (event.button !== 0) return;
54536             var timeout$$1 = window.setTimeout(function() {
54537                     interval$$1 = window.setInterval(nudge.bind(null, d), 100);
54538                 }, 500),
54539                 interval$$1;
54540
54541             function doneNudge() {
54542                 window.clearTimeout(timeout$$1);
54543                 window.clearInterval(interval$$1);
54544                 select(window)
54545                     .on('mouseup.buttonoffset', null, true)
54546                     .on('mousedown.buttonoffset', null, true);
54547             }
54548
54549             select(window)
54550                 .on('mouseup.buttonoffset', doneNudge, true)
54551                 .on('mousedown.buttonoffset', doneNudge, true);
54552
54553             nudge(d);
54554         }
54555
54556
54557         function inputOffset() {
54558             if (event.button !== 0) return;
54559             var input = select(this);
54560             var d = input.node().value;
54561
54562             if (d === '') return resetOffset();
54563
54564             d = d.replace(/;/g, ',').split(',').map(function(n) {
54565                 // if n is NaN, it will always get mapped to false.
54566                 return !isNaN(n) && n;
54567             });
54568
54569             if (d.length !== 2 || !d[0] || !d[1]) {
54570                 input.classed('error', true);
54571                 return;
54572             }
54573
54574             context.background().offset(geoMetersToOffset(d));
54575             updateOffsetVal();
54576         }
54577
54578
54579         function dragOffset() {
54580             if (event.button !== 0) return;
54581             var origin = [event.clientX, event.clientY];
54582
54583             context.container()
54584                 .append('div')
54585                 .attr('class', 'nudge-surface');
54586
54587             select(window)
54588                 .on('mousemove.offset', function() {
54589                     var latest = [event.clientX, event.clientY];
54590                     var d = [
54591                         -(origin[0] - latest[0]) / 4,
54592                         -(origin[1] - latest[1]) / 4
54593                     ];
54594
54595                     origin = latest;
54596                     nudge(d);
54597                 })
54598                 .on('mouseup.offset', function() {
54599                     if (event.button !== 0) return;
54600                     selectAll('.nudge-surface')
54601                         .remove();
54602
54603                     select(window)
54604                         .on('mousemove.offset', null)
54605                         .on('mouseup.offset', null);
54606                 });
54607
54608             event.preventDefault();
54609         }
54610
54611
54612         function hide() {
54613             setVisible(false);
54614         }
54615
54616
54617         function toggle() {
54618             if (event) event.preventDefault();
54619             tooltipBehavior.hide(button);
54620             setVisible(!button.classed('active'));
54621         }
54622
54623
54624         function quickSwitch() {
54625             if (previous) {
54626                 clickSetSource(previous);
54627             }
54628         }
54629
54630
54631         function setVisible(show) {
54632             if (show !== shown) {
54633                 button.classed('active', show);
54634                 shown = show;
54635
54636                 if (show) {
54637                     selection$$1.on('mousedown.background-inside', function() {
54638                         event.stopPropagation();
54639                     });
54640                     content
54641                         .style('display', 'block')
54642                         .style('right', '-300px')
54643                         .transition()
54644                         .duration(200)
54645                         .style('right', '0px');
54646                 } else {
54647                     content
54648                         .style('display', 'block')
54649                         .style('right', '0px')
54650                         .transition()
54651                         .duration(200)
54652                         .style('right', '-300px')
54653                         .on('end', function() {
54654                             select(this).style('display', 'none');
54655                         });
54656                     selection$$1.on('mousedown.background-inside', null);
54657                 }
54658             }
54659         }
54660
54661
54662         var content = selection$$1
54663                 .append('div')
54664                 .attr('class', 'fillL map-overlay col3 content hide'),
54665             tooltipBehavior = tooltip()
54666                 .placement((textDirection === 'rtl') ? 'right' : 'left')
54667                 .html(true)
54668                 .title(uiTooltipHtml(t('background.description'), key)),
54669             button = selection$$1
54670                 .append('button')
54671                 .attr('tabindex', -1)
54672                 .on('click', toggle)
54673                 .call(svgIcon('#icon-layers', 'light'))
54674                 .call(tooltipBehavior),
54675             shown = false;
54676
54677
54678         /* opacity switcher */
54679
54680         var opawrap = content
54681                 .append('div')
54682                 .attr('class', 'opacity-options-wrapper');
54683
54684         opawrap
54685             .append('h4')
54686             .text(t('background.title'));
54687
54688         var opacityList = opawrap
54689             .append('ul')
54690             .attr('class', 'opacity-options');
54691
54692         opacityList.selectAll('div.opacity')
54693             .data(opacities)
54694             .enter()
54695             .append('li')
54696             .attr('data-original-title', function(d) {
54697                 return t('background.percent_brightness', { opacity: (d * 100) });
54698             })
54699             .on('click.set-opacity', setOpacity)
54700             .html('<div class="select-box"></div>')
54701             .call(tooltip()
54702                 .placement((textDirection === 'rtl') ? 'right' : 'left'))
54703             .append('div')
54704             .attr('class', 'opacity')
54705             .style('opacity', function(d) { return 1.25 - d; });
54706
54707
54708         /* background switcher */
54709
54710         var backgroundList = content
54711             .append('ul')
54712             .attr('class', 'layer-list')
54713             .attr('dir', 'auto');
54714
54715         var custom = backgroundList
54716             .append('li')
54717             .attr('class', 'custom_layer')
54718             .datum(rendererBackgroundSource.Custom());
54719
54720         custom
54721             .append('button')
54722             .attr('class', 'layer-browse')
54723             .call(tooltip()
54724                 .title(t('background.custom_button'))
54725                 .placement((textDirection === 'rtl') ? 'right' : 'left'))
54726             .on('click', editCustom)
54727             .call(svgIcon('#icon-search'));
54728
54729         var label = custom
54730             .append('label');
54731
54732         label
54733             .append('input')
54734             .attr('type', 'radio')
54735             .attr('name', 'layers')
54736             .on('change', function () {
54737                 if (customTemplate) {
54738                     setCustom(customTemplate);
54739                 } else {
54740                     editCustom();
54741                 }
54742             });
54743
54744         label
54745             .append('span')
54746             .text(t('background.custom'));
54747
54748         content
54749             .append('div')
54750             .attr('class', 'imagery-faq')
54751             .append('a')
54752             .attr('target', '_blank')
54753             .attr('tabindex', -1)
54754             .call(svgIcon('#icon-out-link', 'inline'))
54755             .attr('href', 'https://github.com/openstreetmap/iD/blob/master/FAQ.md#how-can-i-report-an-issue-with-background-imagery')
54756             .append('span')
54757             .text(t('background.imagery_source_faq'));
54758
54759         var overlayList = content
54760             .append('ul')
54761             .attr('class', 'layer-list');
54762
54763         var controls = content
54764             .append('div')
54765             .attr('class', 'controls-list');
54766
54767
54768         /* minimap toggle */
54769
54770         var minimapLabel = controls
54771             .append('label')
54772             .call(tooltip()
54773                 .html(true)
54774                 .title(uiTooltipHtml(t('background.minimap.tooltip'), '/'))
54775                 .placement('top')
54776             );
54777
54778         minimapLabel
54779             .classed('minimap-toggle', true)
54780             .append('input')
54781             .attr('type', 'checkbox')
54782             .on('change', function() {
54783                 uiMapInMap.toggle();
54784                 event.preventDefault();
54785             });
54786
54787         minimapLabel
54788             .append('span')
54789             .text(t('background.minimap.description'));
54790
54791
54792         /* imagery offset controls */
54793
54794         var adjustments = content
54795             .append('div')
54796             .attr('class', 'adjustments');
54797
54798         adjustments
54799             .append('a')
54800             .text(t('background.fix_misalignment'))
54801             .attr('href', '#')
54802             .classed('hide-toggle', true)
54803             .classed('expanded', false)
54804             .on('click', function() {
54805                 if (event.button !== 0) return;
54806                 var exp = select(this).classed('expanded');
54807                 nudgeContainer.style('display', exp ? 'none' : 'block');
54808                 select(this).classed('expanded', !exp);
54809                 event.preventDefault();
54810             });
54811
54812         var nudgeContainer = adjustments
54813             .append('div')
54814             .attr('class', 'nudge-container cf')
54815             .style('display', 'none');
54816
54817         nudgeContainer
54818             .append('div')
54819             .attr('class', 'nudge-instructions')
54820             .text(t('background.offset'));
54821
54822         var nudgeRect = nudgeContainer
54823             .append('div')
54824             .attr('class', 'nudge-outer-rect')
54825             .on('mousedown', dragOffset);
54826
54827         nudgeRect
54828             .append('div')
54829             .attr('class', 'nudge-inner-rect')
54830             .append('input')
54831             .on('change', inputOffset)
54832             .on('mousedown', function() {
54833                 if (event.button !== 0) return;
54834                 event.stopPropagation();
54835             });
54836
54837         nudgeContainer
54838             .append('div')
54839             .selectAll('button')
54840             .data(directions).enter()
54841             .append('button')
54842             .attr('class', function(d) { return d[0] + ' nudge'; })
54843             .on('mousedown', function(d) {
54844                 if (event.button !== 0) return;
54845                 buttonOffset(d[1]);
54846             });
54847
54848         nudgeContainer
54849             .append('button')
54850             .attr('title', t('background.reset'))
54851             .attr('class', 'nudge-reset disabled')
54852             .on('click', resetOffset)
54853             .call(
54854                 (textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo')
54855             );
54856
54857         context.map()
54858             .on('move.background-update', lodash.debounce(update, 1000));
54859
54860         context.background()
54861             .on('change.background-update', update);
54862
54863
54864         update();
54865         setOpacity(opacityDefault);
54866
54867         var keybinding = d3keybinding('background')
54868             .on(key, toggle)
54869             .on(uiCmd('⌘B'), quickSwitch)
54870             .on('F', hide)
54871             .on('H', hide);
54872
54873         select(document)
54874             .call(keybinding);
54875
54876         context.surface().on('mousedown.background-outside', hide);
54877         context.container().on('mousedown.background-outside', hide);
54878     }
54879
54880     return background;
54881 }
54882
54883 function uiContributors(context) {
54884     var debouncedUpdate = lodash.debounce(function() { update(); }, 1000),
54885         limit = 4,
54886         hidden = false,
54887         wrap = select(null);
54888
54889
54890     function update() {
54891         var users = {},
54892             entities = context.intersects(context.map().extent());
54893
54894         entities.forEach(function(entity) {
54895             if (entity && entity.user) users[entity.user] = true;
54896         });
54897
54898         var u = Object.keys(users),
54899             subset = u.slice(0, u.length > limit ? limit - 1 : limit);
54900
54901         wrap.html('')
54902             .call(svgIcon('#icon-nearby', 'pre-text light'));
54903
54904         var userList = select(document.createElement('span'));
54905
54906         userList.selectAll()
54907             .data(subset)
54908             .enter()
54909             .append('a')
54910             .attr('class', 'user-link')
54911             .attr('href', function(d) { return context.connection().userURL(d); })
54912             .attr('target', '_blank')
54913             .attr('tabindex', -1)
54914             .text(String);
54915
54916         if (u.length > limit) {
54917             var count = select(document.createElement('span'));
54918
54919             count.append('a')
54920                 .attr('target', '_blank')
54921                 .attr('tabindex', -1)
54922                 .attr('href', function() {
54923                     return context.connection().changesetsURL(context.map().center(), context.map().zoom());
54924                 })
54925                 .text(u.length - limit + 1);
54926
54927             wrap.append('span')
54928                 .html(t('contributors.truncated_list', { users: userList.html(), count: count.html() }));
54929
54930         } else {
54931             wrap.append('span')
54932                 .html(t('contributors.list', { users: userList.html() }));
54933         }
54934
54935         if (!u.length) {
54936             hidden = true;
54937             wrap
54938                 .transition()
54939                 .style('opacity', 0);
54940
54941         } else if (hidden) {
54942             wrap
54943                 .transition()
54944                 .style('opacity', 1);
54945         }
54946     }
54947
54948
54949     return function(selection$$1) {
54950         wrap = selection$$1;
54951         update();
54952
54953         context.connection().on('loaded.contributors', debouncedUpdate);
54954         context.map().on('move.contributors', debouncedUpdate);
54955     };
54956 }
54957
54958 function uiFeatureInfo(context) {
54959     function update(selection$$1) {
54960         var features = context.features(),
54961             stats = features.stats(),
54962             count = 0,
54963             hiddenList = lodash.compact(lodash.map(features.hidden(), function(k) {
54964                 if (stats[k]) {
54965                     count += stats[k];
54966                     return String(stats[k]) + ' ' + t('feature.' + k + '.description');
54967                 }
54968             }));
54969
54970         selection$$1.html('');
54971
54972         if (hiddenList.length) {
54973             var tooltipBehavior = tooltip()
54974                     .placement('top')
54975                     .html(true)
54976                     .title(function() {
54977                         return uiTooltipHtml(hiddenList.join('<br/>'));
54978                     });
54979
54980             var warning = selection$$1.append('a')
54981                 .attr('href', '#')
54982                 .attr('tabindex', -1)
54983                 .html(t('feature_info.hidden_warning', { count: count }))
54984                 .call(tooltipBehavior)
54985                 .on('click', function() {
54986                     tooltipBehavior.hide(warning);
54987                     // open map data panel?
54988                     event.preventDefault();
54989                 });
54990         }
54991
54992         selection$$1
54993             .classed('hide', !hiddenList.length);
54994     }
54995
54996
54997     return function(selection$$1) {
54998         update(selection$$1);
54999
55000         context.features().on('change.feature_info', function() {
55001             update(selection$$1);
55002         });
55003     };
55004 }
55005
55006 function uiFullScreen(context) {
55007     var element = context.container().node(),
55008         keybinding = d3keybinding('full-screen');
55009         // button;
55010
55011
55012     function getFullScreenFn() {
55013         if (element.requestFullscreen) {
55014             return element.requestFullscreen;
55015         } else if (element.msRequestFullscreen) {
55016             return element.msRequestFullscreen;
55017         } else if (element.mozRequestFullScreen) {
55018             return element.mozRequestFullScreen;
55019         } else if (element.webkitRequestFullscreen) {
55020             return element.webkitRequestFullscreen;
55021         }
55022     }
55023
55024
55025     function getExitFullScreenFn() {
55026         if (document.exitFullscreen) {
55027             return document.exitFullscreen;
55028         } else if (document.msExitFullscreen) {
55029             return document.msExitFullscreen;
55030         } else if (document.mozCancelFullScreen) {
55031             return document.mozCancelFullScreen;
55032         } else if (document.webkitExitFullscreen) {
55033             return document.webkitExitFullscreen;
55034         }
55035     }
55036
55037
55038     function isFullScreen() {
55039         return document.fullscreenElement ||
55040             document.mozFullScreenElement ||
55041             document.webkitFullscreenElement ||
55042             document.msFullscreenElement;
55043     }
55044
55045
55046     function isSupported() {
55047         return !!getFullScreenFn();
55048     }
55049
55050
55051     function fullScreen() {
55052         event.preventDefault();
55053         if (!isFullScreen()) {
55054             // button.classed('active', true);
55055             getFullScreenFn().apply(element);
55056         } else {
55057             // button.classed('active', false);
55058             getExitFullScreenFn().apply(document);
55059         }
55060     }
55061
55062
55063     return function() { // selection) {
55064         if (!isSupported())
55065             return;
55066
55067         // button = selection.append('button')
55068         //     .attr('title', t('full_screen'))
55069         //     .attr('tabindex', -1)
55070         //     .on('click', fullScreen)
55071         //     .call(tooltip);
55072
55073         // button.append('span')
55074         //     .attr('class', 'icon full-screen');
55075
55076         keybinding
55077             .on('f11', fullScreen)
55078             .on(uiCmd('⌘⇧F'), fullScreen);
55079
55080         select(document)
55081             .call(keybinding);
55082     };
55083 }
55084
55085 function uiModal(selection$$1, blocking) {
55086     var keybinding = d3keybinding('modal');
55087     var previous = selection$$1.select('div.modal');
55088     var animate = previous.empty();
55089
55090     previous.transition()
55091         .duration(200)
55092         .style('opacity', 0)
55093         .remove();
55094
55095     var shaded = selection$$1
55096         .append('div')
55097         .attr('class', 'shaded')
55098         .style('opacity', 0);
55099
55100     shaded.close = function() {
55101         shaded
55102             .transition()
55103             .duration(200)
55104             .style('opacity',0)
55105             .remove();
55106
55107         modal
55108             .transition()
55109             .duration(200)
55110             .style('top','0px');
55111
55112         keybinding.off();
55113     };
55114
55115
55116     var modal = shaded
55117         .append('div')
55118         .attr('class', 'modal fillL col6');
55119
55120     if (!blocking) {
55121         shaded.on('click.remove-modal', function() {
55122             if (event.target === this) {
55123                 shaded.close();
55124             }
55125         });
55126
55127         modal.append('button')
55128             .attr('class', 'close')
55129             .on('click', shaded.close)
55130             .call(svgIcon('#icon-close'));
55131
55132         keybinding
55133             .on('⌫', shaded.close)
55134             .on('⎋', shaded.close);
55135
55136         select(document)
55137             .call(keybinding);
55138     }
55139
55140     modal
55141         .append('div')
55142         .attr('class', 'content');
55143
55144     if (animate) {
55145         shaded.transition().style('opacity', 1);
55146     } else {
55147         shaded.style('opacity', 1);
55148     }
55149
55150
55151     return shaded;
55152 }
55153
55154 function uiLoading(context) {
55155     var message = '',
55156         blocking = false,
55157         modalSelection;
55158
55159
55160     var loading = function(selection) {
55161         modalSelection = uiModal(selection, blocking);
55162
55163         var loadertext = modalSelection.select('.content')
55164             .classed('loading-modal', true)
55165             .append('div')
55166             .attr('class', 'modal-section fillL');
55167
55168         loadertext
55169             .append('img')
55170             .attr('class', 'loader')
55171             .attr('src', context.imagePath('loader-white.gif'));
55172
55173         loadertext
55174             .append('h3')
55175             .text(message);
55176
55177         modalSelection.select('button.close')
55178             .attr('class', 'hide');
55179
55180         return loading;
55181     };
55182
55183
55184     loading.message = function(_) {
55185         if (!arguments.length) return message;
55186         message = _;
55187         return loading;
55188     };
55189
55190
55191     loading.blocking = function(_) {
55192         if (!arguments.length) return blocking;
55193         blocking = _;
55194         return loading;
55195     };
55196
55197
55198     loading.close = function() {
55199         modalSelection.remove();
55200     };
55201
55202
55203     return loading;
55204 }
55205
55206 function uiGeolocate(context) {
55207     var geoOptions = { enableHighAccuracy: false, timeout: 6000 /* 6sec */ },
55208         locating = uiLoading(context).message(t('geolocate.locating')).blocking(true),
55209         timeoutId;
55210
55211
55212     function click() {
55213         context.enter(modeBrowse$$1(context));
55214         context.container().call(locating);
55215         navigator.geolocation.getCurrentPosition(success, error, geoOptions);
55216
55217         // This timeout ensures that we still call finish() even if
55218         // the user declines to share their location in Firefox
55219         timeoutId = setTimeout(finish, 10000 /* 10sec */ );
55220     }
55221
55222
55223     function success(position) {
55224         var map = context.map(),
55225             extent = geoExtent$$1([position.coords.longitude, position.coords.latitude])
55226                 .padByMeters(position.coords.accuracy);
55227
55228         map.centerZoom(extent.center(), Math.min(20, map.extentZoom(extent)));
55229         finish();
55230     }
55231
55232
55233     function error() {
55234         finish();
55235     }
55236
55237
55238     function finish() {
55239         locating.close();  // unblock ui
55240         if (timeoutId) { clearTimeout(timeoutId); }
55241         timeoutId = undefined;
55242     }
55243
55244
55245     return function(selection) {
55246         if (!navigator.geolocation) return;
55247
55248         selection
55249             .append('button')
55250             .attr('tabindex', -1)
55251             .attr('title', t('geolocate.title'))
55252             .on('click', click)
55253             .call(svgIcon('#icon-geolocate', 'light'))
55254             .call(tooltip()
55255                 .placement((textDirection === 'rtl') ? 'right' : 'left'));
55256     };
55257 }
55258
55259 var marked = createCommonjsModule(function (module, exports) {
55260 /**
55261  * marked - a markdown parser
55262  * Copyright (c) 2011-2014, Christopher Jeffrey. (MIT Licensed)
55263  * https://github.com/chjj/marked
55264  */
55265
55266 (function() {
55267
55268 /**
55269  * Block-Level Grammar
55270  */
55271
55272 var block = {
55273   newline: /^\n+/,
55274   code: /^( {4}[^\n]+\n*)+/,
55275   fences: noop,
55276   hr: /^( *[-*_]){3,} *(?:\n+|$)/,
55277   heading: /^ *(#{1,6}) *([^\n]+?) *#* *(?:\n+|$)/,
55278   nptable: noop,
55279   lheading: /^([^\n]+)\n *(=|-){2,} *(?:\n+|$)/,
55280   blockquote: /^( *>[^\n]+(\n(?!def)[^\n]+)*\n*)+/,
55281   list: /^( *)(bull) [\s\S]+?(?:hr|def|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
55282   html: /^ *(?:comment *(?:\n|\s*$)|closed *(?:\n{2,}|\s*$)|closing *(?:\n{2,}|\s*$))/,
55283   def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
55284   table: noop,
55285   paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
55286   text: /^[^\n]+/
55287 };
55288
55289 block.bullet = /(?:[*+-]|\d+\.)/;
55290 block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
55291 block.item = replace(block.item, 'gm')
55292   (/bull/g, block.bullet)
55293   ();
55294
55295 block.list = replace(block.list)
55296   (/bull/g, block.bullet)
55297   ('hr', '\\n+(?=\\1?(?:[-*_] *){3,}(?:\\n+|$))')
55298   ('def', '\\n+(?=' + block.def.source + ')')
55299   ();
55300
55301 block.blockquote = replace(block.blockquote)
55302   ('def', block.def)
55303   ();
55304
55305 block._tag = '(?!(?:'
55306   + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
55307   + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
55308   + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|[^\\w\\s@]*@)\\b';
55309
55310 block.html = replace(block.html)
55311   ('comment', /<!--[\s\S]*?-->/)
55312   ('closed', /<(tag)[\s\S]+?<\/\1>/)
55313   ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
55314   (/tag/g, block._tag)
55315   ();
55316
55317 block.paragraph = replace(block.paragraph)
55318   ('hr', block.hr)
55319   ('heading', block.heading)
55320   ('lheading', block.lheading)
55321   ('blockquote', block.blockquote)
55322   ('tag', '<' + block._tag)
55323   ('def', block.def)
55324   ();
55325
55326 /**
55327  * Normal Block Grammar
55328  */
55329
55330 block.normal = merge({}, block);
55331
55332 /**
55333  * GFM Block Grammar
55334  */
55335
55336 block.gfm = merge({}, block.normal, {
55337   fences: /^ *(`{3,}|~{3,})[ \.]*(\S+)? *\n([\s\S]*?)\s*\1 *(?:\n+|$)/,
55338   paragraph: /^/,
55339   heading: /^ *(#{1,6}) +([^\n]+?) *#* *(?:\n+|$)/
55340 });
55341
55342 block.gfm.paragraph = replace(block.paragraph)
55343   ('(?!', '(?!'
55344     + block.gfm.fences.source.replace('\\1', '\\2') + '|'
55345     + block.list.source.replace('\\1', '\\3') + '|')
55346   ();
55347
55348 /**
55349  * GFM + Tables Block Grammar
55350  */
55351
55352 block.tables = merge({}, block.gfm, {
55353   nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
55354   table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
55355 });
55356
55357 /**
55358  * Block Lexer
55359  */
55360
55361 function Lexer(options) {
55362   this.tokens = [];
55363   this.tokens.links = {};
55364   this.options = options || marked.defaults;
55365   this.rules = block.normal;
55366
55367   if (this.options.gfm) {
55368     if (this.options.tables) {
55369       this.rules = block.tables;
55370     } else {
55371       this.rules = block.gfm;
55372     }
55373   }
55374 }
55375
55376 /**
55377  * Expose Block Rules
55378  */
55379
55380 Lexer.rules = block;
55381
55382 /**
55383  * Static Lex Method
55384  */
55385
55386 Lexer.lex = function(src, options) {
55387   var lexer = new Lexer(options);
55388   return lexer.lex(src);
55389 };
55390
55391 /**
55392  * Preprocessing
55393  */
55394
55395 Lexer.prototype.lex = function(src) {
55396   src = src
55397     .replace(/\r\n|\r/g, '\n')
55398     .replace(/\t/g, '    ')
55399     .replace(/\u00a0/g, ' ')
55400     .replace(/\u2424/g, '\n');
55401
55402   return this.token(src, true);
55403 };
55404
55405 /**
55406  * Lexing
55407  */
55408
55409 Lexer.prototype.token = function(src, top, bq) {
55410   var src = src.replace(/^ +$/gm, '')
55411     , next
55412     , loose
55413     , cap
55414     , bull
55415     , b
55416     , item
55417     , space
55418     , i
55419     , l;
55420
55421   while (src) {
55422     // newline
55423     if (cap = this.rules.newline.exec(src)) {
55424       src = src.substring(cap[0].length);
55425       if (cap[0].length > 1) {
55426         this.tokens.push({
55427           type: 'space'
55428         });
55429       }
55430     }
55431
55432     // code
55433     if (cap = this.rules.code.exec(src)) {
55434       src = src.substring(cap[0].length);
55435       cap = cap[0].replace(/^ {4}/gm, '');
55436       this.tokens.push({
55437         type: 'code',
55438         text: !this.options.pedantic
55439           ? cap.replace(/\n+$/, '')
55440           : cap
55441       });
55442       continue;
55443     }
55444
55445     // fences (gfm)
55446     if (cap = this.rules.fences.exec(src)) {
55447       src = src.substring(cap[0].length);
55448       this.tokens.push({
55449         type: 'code',
55450         lang: cap[2],
55451         text: cap[3] || ''
55452       });
55453       continue;
55454     }
55455
55456     // heading
55457     if (cap = this.rules.heading.exec(src)) {
55458       src = src.substring(cap[0].length);
55459       this.tokens.push({
55460         type: 'heading',
55461         depth: cap[1].length,
55462         text: cap[2]
55463       });
55464       continue;
55465     }
55466
55467     // table no leading pipe (gfm)
55468     if (top && (cap = this.rules.nptable.exec(src))) {
55469       src = src.substring(cap[0].length);
55470
55471       item = {
55472         type: 'table',
55473         header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
55474         align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
55475         cells: cap[3].replace(/\n$/, '').split('\n')
55476       };
55477
55478       for (i = 0; i < item.align.length; i++) {
55479         if (/^ *-+: *$/.test(item.align[i])) {
55480           item.align[i] = 'right';
55481         } else if (/^ *:-+: *$/.test(item.align[i])) {
55482           item.align[i] = 'center';
55483         } else if (/^ *:-+ *$/.test(item.align[i])) {
55484           item.align[i] = 'left';
55485         } else {
55486           item.align[i] = null;
55487         }
55488       }
55489
55490       for (i = 0; i < item.cells.length; i++) {
55491         item.cells[i] = item.cells[i].split(/ *\| */);
55492       }
55493
55494       this.tokens.push(item);
55495
55496       continue;
55497     }
55498
55499     // lheading
55500     if (cap = this.rules.lheading.exec(src)) {
55501       src = src.substring(cap[0].length);
55502       this.tokens.push({
55503         type: 'heading',
55504         depth: cap[2] === '=' ? 1 : 2,
55505         text: cap[1]
55506       });
55507       continue;
55508     }
55509
55510     // hr
55511     if (cap = this.rules.hr.exec(src)) {
55512       src = src.substring(cap[0].length);
55513       this.tokens.push({
55514         type: 'hr'
55515       });
55516       continue;
55517     }
55518
55519     // blockquote
55520     if (cap = this.rules.blockquote.exec(src)) {
55521       src = src.substring(cap[0].length);
55522
55523       this.tokens.push({
55524         type: 'blockquote_start'
55525       });
55526
55527       cap = cap[0].replace(/^ *> ?/gm, '');
55528
55529       // Pass `top` to keep the current
55530       // "toplevel" state. This is exactly
55531       // how markdown.pl works.
55532       this.token(cap, top, true);
55533
55534       this.tokens.push({
55535         type: 'blockquote_end'
55536       });
55537
55538       continue;
55539     }
55540
55541     // list
55542     if (cap = this.rules.list.exec(src)) {
55543       src = src.substring(cap[0].length);
55544       bull = cap[2];
55545
55546       this.tokens.push({
55547         type: 'list_start',
55548         ordered: bull.length > 1
55549       });
55550
55551       // Get each top-level item.
55552       cap = cap[0].match(this.rules.item);
55553
55554       next = false;
55555       l = cap.length;
55556       i = 0;
55557
55558       for (; i < l; i++) {
55559         item = cap[i];
55560
55561         // Remove the list item's bullet
55562         // so it is seen as the next token.
55563         space = item.length;
55564         item = item.replace(/^ *([*+-]|\d+\.) +/, '');
55565
55566         // Outdent whatever the
55567         // list item contains. Hacky.
55568         if (~item.indexOf('\n ')) {
55569           space -= item.length;
55570           item = !this.options.pedantic
55571             ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
55572             : item.replace(/^ {1,4}/gm, '');
55573         }
55574
55575         // Determine whether the next list item belongs here.
55576         // Backpedal if it does not belong in this list.
55577         if (this.options.smartLists && i !== l - 1) {
55578           b = block.bullet.exec(cap[i + 1])[0];
55579           if (bull !== b && !(bull.length > 1 && b.length > 1)) {
55580             src = cap.slice(i + 1).join('\n') + src;
55581             i = l - 1;
55582           }
55583         }
55584
55585         // Determine whether item is loose or not.
55586         // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
55587         // for discount behavior.
55588         loose = next || /\n\n(?!\s*$)/.test(item);
55589         if (i !== l - 1) {
55590           next = item.charAt(item.length - 1) === '\n';
55591           if (!loose) loose = next;
55592         }
55593
55594         this.tokens.push({
55595           type: loose
55596             ? 'loose_item_start'
55597             : 'list_item_start'
55598         });
55599
55600         // Recurse.
55601         this.token(item, false, bq);
55602
55603         this.tokens.push({
55604           type: 'list_item_end'
55605         });
55606       }
55607
55608       this.tokens.push({
55609         type: 'list_end'
55610       });
55611
55612       continue;
55613     }
55614
55615     // html
55616     if (cap = this.rules.html.exec(src)) {
55617       src = src.substring(cap[0].length);
55618       this.tokens.push({
55619         type: this.options.sanitize
55620           ? 'paragraph'
55621           : 'html',
55622         pre: !this.options.sanitizer
55623           && (cap[1] === 'pre' || cap[1] === 'script' || cap[1] === 'style'),
55624         text: cap[0]
55625       });
55626       continue;
55627     }
55628
55629     // def
55630     if ((!bq && top) && (cap = this.rules.def.exec(src))) {
55631       src = src.substring(cap[0].length);
55632       this.tokens.links[cap[1].toLowerCase()] = {
55633         href: cap[2],
55634         title: cap[3]
55635       };
55636       continue;
55637     }
55638
55639     // table (gfm)
55640     if (top && (cap = this.rules.table.exec(src))) {
55641       src = src.substring(cap[0].length);
55642
55643       item = {
55644         type: 'table',
55645         header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
55646         align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
55647         cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
55648       };
55649
55650       for (i = 0; i < item.align.length; i++) {
55651         if (/^ *-+: *$/.test(item.align[i])) {
55652           item.align[i] = 'right';
55653         } else if (/^ *:-+: *$/.test(item.align[i])) {
55654           item.align[i] = 'center';
55655         } else if (/^ *:-+ *$/.test(item.align[i])) {
55656           item.align[i] = 'left';
55657         } else {
55658           item.align[i] = null;
55659         }
55660       }
55661
55662       for (i = 0; i < item.cells.length; i++) {
55663         item.cells[i] = item.cells[i]
55664           .replace(/^ *\| *| *\| *$/g, '')
55665           .split(/ *\| */);
55666       }
55667
55668       this.tokens.push(item);
55669
55670       continue;
55671     }
55672
55673     // top-level paragraph
55674     if (top && (cap = this.rules.paragraph.exec(src))) {
55675       src = src.substring(cap[0].length);
55676       this.tokens.push({
55677         type: 'paragraph',
55678         text: cap[1].charAt(cap[1].length - 1) === '\n'
55679           ? cap[1].slice(0, -1)
55680           : cap[1]
55681       });
55682       continue;
55683     }
55684
55685     // text
55686     if (cap = this.rules.text.exec(src)) {
55687       // Top-level should never reach here.
55688       src = src.substring(cap[0].length);
55689       this.tokens.push({
55690         type: 'text',
55691         text: cap[0]
55692       });
55693       continue;
55694     }
55695
55696     if (src) {
55697       throw new
55698         Error('Infinite loop on byte: ' + src.charCodeAt(0));
55699     }
55700   }
55701
55702   return this.tokens;
55703 };
55704
55705 /**
55706  * Inline-Level Grammar
55707  */
55708
55709 var inline = {
55710   escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
55711   autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
55712   url: noop,
55713   tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
55714   link: /^!?\[(inside)\]\(href\)/,
55715   reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
55716   nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
55717   strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
55718   em: /^\b_((?:[^_]|__)+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
55719   code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
55720   br: /^ {2,}\n(?!\s*$)/,
55721   del: noop,
55722   text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
55723 };
55724
55725 inline._inside = /(?:\[[^\]]*\]|[^\[\]]|\](?=[^\[]*\]))*/;
55726 inline._href = /\s*<?([\s\S]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;
55727
55728 inline.link = replace(inline.link)
55729   ('inside', inline._inside)
55730   ('href', inline._href)
55731   ();
55732
55733 inline.reflink = replace(inline.reflink)
55734   ('inside', inline._inside)
55735   ();
55736
55737 /**
55738  * Normal Inline Grammar
55739  */
55740
55741 inline.normal = merge({}, inline);
55742
55743 /**
55744  * Pedantic Inline Grammar
55745  */
55746
55747 inline.pedantic = merge({}, inline.normal, {
55748   strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
55749   em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
55750 });
55751
55752 /**
55753  * GFM Inline Grammar
55754  */
55755
55756 inline.gfm = merge({}, inline.normal, {
55757   escape: replace(inline.escape)('])', '~|])')(),
55758   url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
55759   del: /^~~(?=\S)([\s\S]*?\S)~~/,
55760   text: replace(inline.text)
55761     (']|', '~]|')
55762     ('|', '|https?://|')
55763     ()
55764 });
55765
55766 /**
55767  * GFM + Line Breaks Inline Grammar
55768  */
55769
55770 inline.breaks = merge({}, inline.gfm, {
55771   br: replace(inline.br)('{2,}', '*')(),
55772   text: replace(inline.gfm.text)('{2,}', '*')()
55773 });
55774
55775 /**
55776  * Inline Lexer & Compiler
55777  */
55778
55779 function InlineLexer(links, options) {
55780   this.options = options || marked.defaults;
55781   this.links = links;
55782   this.rules = inline.normal;
55783   this.renderer = this.options.renderer || new Renderer;
55784   this.renderer.options = this.options;
55785
55786   if (!this.links) {
55787     throw new
55788       Error('Tokens array requires a `links` property.');
55789   }
55790
55791   if (this.options.gfm) {
55792     if (this.options.breaks) {
55793       this.rules = inline.breaks;
55794     } else {
55795       this.rules = inline.gfm;
55796     }
55797   } else if (this.options.pedantic) {
55798     this.rules = inline.pedantic;
55799   }
55800 }
55801
55802 /**
55803  * Expose Inline Rules
55804  */
55805
55806 InlineLexer.rules = inline;
55807
55808 /**
55809  * Static Lexing/Compiling Method
55810  */
55811
55812 InlineLexer.output = function(src, links, options) {
55813   var inline = new InlineLexer(links, options);
55814   return inline.output(src);
55815 };
55816
55817 /**
55818  * Lexing/Compiling
55819  */
55820
55821 InlineLexer.prototype.output = function(src) {
55822   var out = ''
55823     , link
55824     , text
55825     , href
55826     , cap;
55827
55828   while (src) {
55829     // escape
55830     if (cap = this.rules.escape.exec(src)) {
55831       src = src.substring(cap[0].length);
55832       out += cap[1];
55833       continue;
55834     }
55835
55836     // autolink
55837     if (cap = this.rules.autolink.exec(src)) {
55838       src = src.substring(cap[0].length);
55839       if (cap[2] === '@') {
55840         text = cap[1].charAt(6) === ':'
55841           ? this.mangle(cap[1].substring(7))
55842           : this.mangle(cap[1]);
55843         href = this.mangle('mailto:') + text;
55844       } else {
55845         text = escape(cap[1]);
55846         href = text;
55847       }
55848       out += this.renderer.link(href, null, text);
55849       continue;
55850     }
55851
55852     // url (gfm)
55853     if (!this.inLink && (cap = this.rules.url.exec(src))) {
55854       src = src.substring(cap[0].length);
55855       text = escape(cap[1]);
55856       href = text;
55857       out += this.renderer.link(href, null, text);
55858       continue;
55859     }
55860
55861     // tag
55862     if (cap = this.rules.tag.exec(src)) {
55863       if (!this.inLink && /^<a /i.test(cap[0])) {
55864         this.inLink = true;
55865       } else if (this.inLink && /^<\/a>/i.test(cap[0])) {
55866         this.inLink = false;
55867       }
55868       src = src.substring(cap[0].length);
55869       out += this.options.sanitize
55870         ? this.options.sanitizer
55871           ? this.options.sanitizer(cap[0])
55872           : escape(cap[0])
55873         : cap[0];
55874       continue;
55875     }
55876
55877     // link
55878     if (cap = this.rules.link.exec(src)) {
55879       src = src.substring(cap[0].length);
55880       this.inLink = true;
55881       out += this.outputLink(cap, {
55882         href: cap[2],
55883         title: cap[3]
55884       });
55885       this.inLink = false;
55886       continue;
55887     }
55888
55889     // reflink, nolink
55890     if ((cap = this.rules.reflink.exec(src))
55891         || (cap = this.rules.nolink.exec(src))) {
55892       src = src.substring(cap[0].length);
55893       link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
55894       link = this.links[link.toLowerCase()];
55895       if (!link || !link.href) {
55896         out += cap[0].charAt(0);
55897         src = cap[0].substring(1) + src;
55898         continue;
55899       }
55900       this.inLink = true;
55901       out += this.outputLink(cap, link);
55902       this.inLink = false;
55903       continue;
55904     }
55905
55906     // strong
55907     if (cap = this.rules.strong.exec(src)) {
55908       src = src.substring(cap[0].length);
55909       out += this.renderer.strong(this.output(cap[2] || cap[1]));
55910       continue;
55911     }
55912
55913     // em
55914     if (cap = this.rules.em.exec(src)) {
55915       src = src.substring(cap[0].length);
55916       out += this.renderer.em(this.output(cap[2] || cap[1]));
55917       continue;
55918     }
55919
55920     // code
55921     if (cap = this.rules.code.exec(src)) {
55922       src = src.substring(cap[0].length);
55923       out += this.renderer.codespan(escape(cap[2], true));
55924       continue;
55925     }
55926
55927     // br
55928     if (cap = this.rules.br.exec(src)) {
55929       src = src.substring(cap[0].length);
55930       out += this.renderer.br();
55931       continue;
55932     }
55933
55934     // del (gfm)
55935     if (cap = this.rules.del.exec(src)) {
55936       src = src.substring(cap[0].length);
55937       out += this.renderer.del(this.output(cap[1]));
55938       continue;
55939     }
55940
55941     // text
55942     if (cap = this.rules.text.exec(src)) {
55943       src = src.substring(cap[0].length);
55944       out += this.renderer.text(escape(this.smartypants(cap[0])));
55945       continue;
55946     }
55947
55948     if (src) {
55949       throw new
55950         Error('Infinite loop on byte: ' + src.charCodeAt(0));
55951     }
55952   }
55953
55954   return out;
55955 };
55956
55957 /**
55958  * Compile Link
55959  */
55960
55961 InlineLexer.prototype.outputLink = function(cap, link) {
55962   var href = escape(link.href)
55963     , title = link.title ? escape(link.title) : null;
55964
55965   return cap[0].charAt(0) !== '!'
55966     ? this.renderer.link(href, title, this.output(cap[1]))
55967     : this.renderer.image(href, title, escape(cap[1]));
55968 };
55969
55970 /**
55971  * Smartypants Transformations
55972  */
55973
55974 InlineLexer.prototype.smartypants = function(text) {
55975   if (!this.options.smartypants) return text;
55976   return text
55977     // em-dashes
55978     .replace(/---/g, '\u2014')
55979     // en-dashes
55980     .replace(/--/g, '\u2013')
55981     // opening singles
55982     .replace(/(^|[-\u2014/(\[{"\s])'/g, '$1\u2018')
55983     // closing singles & apostrophes
55984     .replace(/'/g, '\u2019')
55985     // opening doubles
55986     .replace(/(^|[-\u2014/(\[{\u2018\s])"/g, '$1\u201c')
55987     // closing doubles
55988     .replace(/"/g, '\u201d')
55989     // ellipses
55990     .replace(/\.{3}/g, '\u2026');
55991 };
55992
55993 /**
55994  * Mangle Links
55995  */
55996
55997 InlineLexer.prototype.mangle = function(text) {
55998   if (!this.options.mangle) return text;
55999   var out = ''
56000     , l = text.length
56001     , i = 0
56002     , ch;
56003
56004   for (; i < l; i++) {
56005     ch = text.charCodeAt(i);
56006     if (Math.random() > 0.5) {
56007       ch = 'x' + ch.toString(16);
56008     }
56009     out += '&#' + ch + ';';
56010   }
56011
56012   return out;
56013 };
56014
56015 /**
56016  * Renderer
56017  */
56018
56019 function Renderer(options) {
56020   this.options = options || {};
56021 }
56022
56023 Renderer.prototype.code = function(code, lang, escaped) {
56024   if (this.options.highlight) {
56025     var out = this.options.highlight(code, lang);
56026     if (out != null && out !== code) {
56027       escaped = true;
56028       code = out;
56029     }
56030   }
56031
56032   if (!lang) {
56033     return '<pre><code>'
56034       + (escaped ? code : escape(code, true))
56035       + '\n</code></pre>';
56036   }
56037
56038   return '<pre><code class="'
56039     + this.options.langPrefix
56040     + escape(lang, true)
56041     + '">'
56042     + (escaped ? code : escape(code, true))
56043     + '\n</code></pre>\n';
56044 };
56045
56046 Renderer.prototype.blockquote = function(quote) {
56047   return '<blockquote>\n' + quote + '</blockquote>\n';
56048 };
56049
56050 Renderer.prototype.html = function(html) {
56051   return html;
56052 };
56053
56054 Renderer.prototype.heading = function(text, level, raw) {
56055   return '<h'
56056     + level
56057     + ' id="'
56058     + this.options.headerPrefix
56059     + raw.toLowerCase().replace(/[^\w]+/g, '-')
56060     + '">'
56061     + text
56062     + '</h'
56063     + level
56064     + '>\n';
56065 };
56066
56067 Renderer.prototype.hr = function() {
56068   return this.options.xhtml ? '<hr/>\n' : '<hr>\n';
56069 };
56070
56071 Renderer.prototype.list = function(body, ordered) {
56072   var type = ordered ? 'ol' : 'ul';
56073   return '<' + type + '>\n' + body + '</' + type + '>\n';
56074 };
56075
56076 Renderer.prototype.listitem = function(text) {
56077   return '<li>' + text + '</li>\n';
56078 };
56079
56080 Renderer.prototype.paragraph = function(text) {
56081   return '<p>' + text + '</p>\n';
56082 };
56083
56084 Renderer.prototype.table = function(header, body) {
56085   return '<table>\n'
56086     + '<thead>\n'
56087     + header
56088     + '</thead>\n'
56089     + '<tbody>\n'
56090     + body
56091     + '</tbody>\n'
56092     + '</table>\n';
56093 };
56094
56095 Renderer.prototype.tablerow = function(content) {
56096   return '<tr>\n' + content + '</tr>\n';
56097 };
56098
56099 Renderer.prototype.tablecell = function(content, flags) {
56100   var type = flags.header ? 'th' : 'td';
56101   var tag = flags.align
56102     ? '<' + type + ' style="text-align:' + flags.align + '">'
56103     : '<' + type + '>';
56104   return tag + content + '</' + type + '>\n';
56105 };
56106
56107 // span level renderer
56108 Renderer.prototype.strong = function(text) {
56109   return '<strong>' + text + '</strong>';
56110 };
56111
56112 Renderer.prototype.em = function(text) {
56113   return '<em>' + text + '</em>';
56114 };
56115
56116 Renderer.prototype.codespan = function(text) {
56117   return '<code>' + text + '</code>';
56118 };
56119
56120 Renderer.prototype.br = function() {
56121   return this.options.xhtml ? '<br/>' : '<br>';
56122 };
56123
56124 Renderer.prototype.del = function(text) {
56125   return '<del>' + text + '</del>';
56126 };
56127
56128 Renderer.prototype.link = function(href, title, text) {
56129   if (this.options.sanitize) {
56130     try {
56131       var prot = decodeURIComponent(unescape(href))
56132         .replace(/[^\w:]/g, '')
56133         .toLowerCase();
56134     } catch (e) {
56135       return '';
56136     }
56137     if (prot.indexOf('javascript:') === 0 || prot.indexOf('vbscript:') === 0) {
56138       return '';
56139     }
56140   }
56141   var out = '<a href="' + href + '"';
56142   if (title) {
56143     out += ' title="' + title + '"';
56144   }
56145   out += '>' + text + '</a>';
56146   return out;
56147 };
56148
56149 Renderer.prototype.image = function(href, title, text) {
56150   var out = '<img src="' + href + '" alt="' + text + '"';
56151   if (title) {
56152     out += ' title="' + title + '"';
56153   }
56154   out += this.options.xhtml ? '/>' : '>';
56155   return out;
56156 };
56157
56158 Renderer.prototype.text = function(text) {
56159   return text;
56160 };
56161
56162 /**
56163  * Parsing & Compiling
56164  */
56165
56166 function Parser(options) {
56167   this.tokens = [];
56168   this.token = null;
56169   this.options = options || marked.defaults;
56170   this.options.renderer = this.options.renderer || new Renderer;
56171   this.renderer = this.options.renderer;
56172   this.renderer.options = this.options;
56173 }
56174
56175 /**
56176  * Static Parse Method
56177  */
56178
56179 Parser.parse = function(src, options, renderer) {
56180   var parser = new Parser(options, renderer);
56181   return parser.parse(src);
56182 };
56183
56184 /**
56185  * Parse Loop
56186  */
56187
56188 Parser.prototype.parse = function(src) {
56189   this.inline = new InlineLexer(src.links, this.options, this.renderer);
56190   this.tokens = src.reverse();
56191
56192   var out = '';
56193   while (this.next()) {
56194     out += this.tok();
56195   }
56196
56197   return out;
56198 };
56199
56200 /**
56201  * Next Token
56202  */
56203
56204 Parser.prototype.next = function() {
56205   return this.token = this.tokens.pop();
56206 };
56207
56208 /**
56209  * Preview Next Token
56210  */
56211
56212 Parser.prototype.peek = function() {
56213   return this.tokens[this.tokens.length - 1] || 0;
56214 };
56215
56216 /**
56217  * Parse Text Tokens
56218  */
56219
56220 Parser.prototype.parseText = function() {
56221   var body = this.token.text;
56222
56223   while (this.peek().type === 'text') {
56224     body += '\n' + this.next().text;
56225   }
56226
56227   return this.inline.output(body);
56228 };
56229
56230 /**
56231  * Parse Current Token
56232  */
56233
56234 Parser.prototype.tok = function() {
56235   switch (this.token.type) {
56236     case 'space': {
56237       return '';
56238     }
56239     case 'hr': {
56240       return this.renderer.hr();
56241     }
56242     case 'heading': {
56243       return this.renderer.heading(
56244         this.inline.output(this.token.text),
56245         this.token.depth,
56246         this.token.text);
56247     }
56248     case 'code': {
56249       return this.renderer.code(this.token.text,
56250         this.token.lang,
56251         this.token.escaped);
56252     }
56253     case 'table': {
56254       var header = ''
56255         , body = ''
56256         , i
56257         , row
56258         , cell
56259         , flags
56260         , j;
56261
56262       // header
56263       cell = '';
56264       for (i = 0; i < this.token.header.length; i++) {
56265         flags = { header: true, align: this.token.align[i] };
56266         cell += this.renderer.tablecell(
56267           this.inline.output(this.token.header[i]),
56268           { header: true, align: this.token.align[i] }
56269         );
56270       }
56271       header += this.renderer.tablerow(cell);
56272
56273       for (i = 0; i < this.token.cells.length; i++) {
56274         row = this.token.cells[i];
56275
56276         cell = '';
56277         for (j = 0; j < row.length; j++) {
56278           cell += this.renderer.tablecell(
56279             this.inline.output(row[j]),
56280             { header: false, align: this.token.align[j] }
56281           );
56282         }
56283
56284         body += this.renderer.tablerow(cell);
56285       }
56286       return this.renderer.table(header, body);
56287     }
56288     case 'blockquote_start': {
56289       var body = '';
56290
56291       while (this.next().type !== 'blockquote_end') {
56292         body += this.tok();
56293       }
56294
56295       return this.renderer.blockquote(body);
56296     }
56297     case 'list_start': {
56298       var body = ''
56299         , ordered = this.token.ordered;
56300
56301       while (this.next().type !== 'list_end') {
56302         body += this.tok();
56303       }
56304
56305       return this.renderer.list(body, ordered);
56306     }
56307     case 'list_item_start': {
56308       var body = '';
56309
56310       while (this.next().type !== 'list_item_end') {
56311         body += this.token.type === 'text'
56312           ? this.parseText()
56313           : this.tok();
56314       }
56315
56316       return this.renderer.listitem(body);
56317     }
56318     case 'loose_item_start': {
56319       var body = '';
56320
56321       while (this.next().type !== 'list_item_end') {
56322         body += this.tok();
56323       }
56324
56325       return this.renderer.listitem(body);
56326     }
56327     case 'html': {
56328       var html = !this.token.pre && !this.options.pedantic
56329         ? this.inline.output(this.token.text)
56330         : this.token.text;
56331       return this.renderer.html(html);
56332     }
56333     case 'paragraph': {
56334       return this.renderer.paragraph(this.inline.output(this.token.text));
56335     }
56336     case 'text': {
56337       return this.renderer.paragraph(this.parseText());
56338     }
56339   }
56340 };
56341
56342 /**
56343  * Helpers
56344  */
56345
56346 function escape(html, encode) {
56347   return html
56348     .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&amp;')
56349     .replace(/</g, '&lt;')
56350     .replace(/>/g, '&gt;')
56351     .replace(/"/g, '&quot;')
56352     .replace(/'/g, '&#39;');
56353 }
56354
56355 function unescape(html) {
56356         // explicitly match decimal, hex, and named HTML entities 
56357   return html.replace(/&(#(?:\d+)|(?:#x[0-9A-Fa-f]+)|(?:\w+));?/g, function(_, n) {
56358     n = n.toLowerCase();
56359     if (n === 'colon') return ':';
56360     if (n.charAt(0) === '#') {
56361       return n.charAt(1) === 'x'
56362         ? String.fromCharCode(parseInt(n.substring(2), 16))
56363         : String.fromCharCode(+n.substring(1));
56364     }
56365     return '';
56366   });
56367 }
56368
56369 function replace(regex, opt) {
56370   regex = regex.source;
56371   opt = opt || '';
56372   return function self(name, val) {
56373     if (!name) return new RegExp(regex, opt);
56374     val = val.source || val;
56375     val = val.replace(/(^|[^\[])\^/g, '$1');
56376     regex = regex.replace(name, val);
56377     return self;
56378   };
56379 }
56380
56381 function noop() {}
56382 noop.exec = noop;
56383
56384 function merge(obj) {
56385   var i = 1
56386     , target
56387     , key;
56388
56389   for (; i < arguments.length; i++) {
56390     target = arguments[i];
56391     for (key in target) {
56392       if (Object.prototype.hasOwnProperty.call(target, key)) {
56393         obj[key] = target[key];
56394       }
56395     }
56396   }
56397
56398   return obj;
56399 }
56400
56401
56402 /**
56403  * Marked
56404  */
56405
56406 function marked(src, opt, callback) {
56407   if (callback || typeof opt === 'function') {
56408     if (!callback) {
56409       callback = opt;
56410       opt = null;
56411     }
56412
56413     opt = merge({}, marked.defaults, opt || {});
56414
56415     var highlight = opt.highlight
56416       , tokens
56417       , pending
56418       , i = 0;
56419
56420     try {
56421       tokens = Lexer.lex(src, opt);
56422     } catch (e) {
56423       return callback(e);
56424     }
56425
56426     pending = tokens.length;
56427
56428     var done = function(err) {
56429       if (err) {
56430         opt.highlight = highlight;
56431         return callback(err);
56432       }
56433
56434       var out;
56435
56436       try {
56437         out = Parser.parse(tokens, opt);
56438       } catch (e) {
56439         err = e;
56440       }
56441
56442       opt.highlight = highlight;
56443
56444       return err
56445         ? callback(err)
56446         : callback(null, out);
56447     };
56448
56449     if (!highlight || highlight.length < 3) {
56450       return done();
56451     }
56452
56453     delete opt.highlight;
56454
56455     if (!pending) return done();
56456
56457     for (; i < tokens.length; i++) {
56458       (function(token) {
56459         if (token.type !== 'code') {
56460           return --pending || done();
56461         }
56462         return highlight(token.text, token.lang, function(err, code) {
56463           if (err) return done(err);
56464           if (code == null || code === token.text) {
56465             return --pending || done();
56466           }
56467           token.text = code;
56468           token.escaped = true;
56469           --pending || done();
56470         });
56471       })(tokens[i]);
56472     }
56473
56474     return;
56475   }
56476   try {
56477     if (opt) opt = merge({}, marked.defaults, opt);
56478     return Parser.parse(Lexer.lex(src, opt), opt);
56479   } catch (e) {
56480     e.message += '\nPlease report this to https://github.com/chjj/marked.';
56481     if ((opt || marked.defaults).silent) {
56482       return '<p>An error occured:</p><pre>'
56483         + escape(e.message + '', true)
56484         + '</pre>';
56485     }
56486     throw e;
56487   }
56488 }
56489
56490 /**
56491  * Options
56492  */
56493
56494 marked.options =
56495 marked.setOptions = function(opt) {
56496   merge(marked.defaults, opt);
56497   return marked;
56498 };
56499
56500 marked.defaults = {
56501   gfm: true,
56502   tables: true,
56503   breaks: false,
56504   pedantic: false,
56505   sanitize: false,
56506   sanitizer: null,
56507   mangle: true,
56508   smartLists: false,
56509   silent: false,
56510   highlight: null,
56511   langPrefix: 'lang-',
56512   smartypants: false,
56513   headerPrefix: '',
56514   renderer: new Renderer,
56515   xhtml: false
56516 };
56517
56518 /**
56519  * Expose
56520  */
56521
56522 marked.Parser = Parser;
56523 marked.parser = Parser.parse;
56524
56525 marked.Renderer = Renderer;
56526
56527 marked.Lexer = Lexer;
56528 marked.lexer = Lexer.lex;
56529
56530 marked.InlineLexer = InlineLexer;
56531 marked.inlineLexer = InlineLexer.output;
56532
56533 marked.parse = marked;
56534
56535 if (typeof module !== 'undefined' && typeof exports === 'object') {
56536   module.exports = marked;
56537 } else if (typeof define === 'function' && define.amd) {
56538   define(function() { return marked; });
56539 } else {
56540   this.marked = marked;
56541 }
56542
56543 }).call(function() {
56544   return this || (typeof window !== 'undefined' ? window : commonjsGlobal);
56545 }());
56546 });
56547
56548 // toggles the visibility of ui elements, using a combination of the
56549 // hide class, which sets display=none, and a d3 transition for opacity.
56550 // this will cause blinking when called repeatedly, so check that the
56551 // value actually changes between calls.
56552 function uiToggle(show, callback) {
56553     return function(selection$$1) {
56554         selection$$1
56555             .style('opacity', show ? 0 : 1)
56556             .classed('hide', false)
56557             .transition()
56558             .style('opacity', show ? 1 : 0)
56559             .on('end', function() {
56560                 select(this)
56561                     .classed('hide', !show)
56562                     .style('opacity', null);
56563                 if (callback) callback.apply(this);
56564             });
56565     };
56566 }
56567
56568 // Tooltips and svg mask used to highlight certain features
56569 function d3curtain() {
56570
56571     var dispatch$$1 = dispatch(),
56572         surface = select(null),
56573         tooltip = select(null),
56574         darkness = select(null);
56575
56576     function curtain(selection$$1) {
56577         surface = selection$$1
56578             .append('svg')
56579             .attr('id', 'curtain')
56580             .style('z-index', 1000)
56581             .style('pointer-events', 'none')
56582             .style('position', 'absolute')
56583             .style('top', 0)
56584             .style('left', 0);
56585
56586         darkness = surface.append('path')
56587             .attr('x', 0)
56588             .attr('y', 0)
56589             .attr('class', 'curtain-darkness');
56590
56591         select(window).on('resize.curtain', resize);
56592
56593         tooltip = selection$$1.append('div')
56594             .attr('class', 'tooltip')
56595             .style('z-index', 1002);
56596
56597         tooltip
56598             .append('div')
56599             .attr('class', 'tooltip-arrow');
56600
56601         tooltip
56602             .append('div')
56603             .attr('class', 'tooltip-inner');
56604
56605         resize();
56606
56607
56608         function resize() {
56609             surface
56610                 .attr('width', window.innerWidth)
56611                 .attr('height', window.innerHeight);
56612             curtain.cut(darkness.datum());
56613         }
56614     }
56615
56616
56617     curtain.reveal = function(box, text$$1, tooltipclass, duration) {
56618         if (typeof box === 'string') box = select(box).node();
56619         if (box.getBoundingClientRect) box = box.getBoundingClientRect();
56620
56621         curtain.cut(box, duration);
56622
56623         if (text$$1) {
56624             // pseudo markdown bold text hack
56625             var parts = text$$1.split('**');
56626             var html$$1 = parts[0] ? '<span>' + parts[0] + '</span>' : '';
56627             if (parts[1]) html$$1 += '<span class="bold">' + parts[1] + '</span>';
56628
56629             var selection$$1 = tooltip
56630                 .classed('in', true)
56631                 .selectAll('.tooltip-inner')
56632                 .html(html$$1);
56633
56634             var dimensions = utilGetDimensions(selection$$1, true),
56635                 w = window.innerWidth,
56636                 h = window.innerHeight,
56637                 side, pos;
56638
56639             // trim box dimensions to just the portion that fits in the window..
56640             if (box.top + box.height > h) {
56641                 box.height -= (box.top + box.height - h);
56642             }
56643             if (box.left + box.width > w) {
56644                 box.width -= (box.left + box.width - w);
56645             }
56646
56647             // determine tooltip placement..
56648             if (box.top + box.height < Math.min(100, box.width + box.left)) {
56649                 side = 'bottom';
56650                 pos = [box.left + box.width / 2 - dimensions[0] / 2, box.top + box.height];
56651
56652             } else if (box.left + box.width + 300 < w) {
56653                 side = 'right';
56654                 pos = [box.left + box.width, box.top + box.height / 2 - dimensions[1] / 2];
56655
56656             } else if (box.left > 300) {
56657                 side = 'left';
56658                 pos = [box.left - 200, box.top + box.height / 2 - dimensions[1] / 2];
56659
56660             } else {
56661                 side = 'bottom';
56662                 pos = [box.left, box.top + box.height];
56663             }
56664
56665             pos = [
56666                 Math.min(Math.max(10, pos[0]), w - dimensions[0] - 10),
56667                 Math.min(Math.max(10, pos[1]), h - dimensions[1] - 10)
56668             ];
56669
56670             if (duration !== 0 || !tooltip.classed(side)) {
56671                 tooltip.call(uiToggle(true));
56672             }
56673
56674             tooltip
56675                 .style('top', pos[1] + 'px')
56676                 .style('left', pos[0] + 'px')
56677                 .attr('class', 'curtain-tooltip tooltip in ' + side + ' ' + tooltipclass);
56678
56679         } else {
56680             tooltip.call(uiToggle(false));
56681         }
56682     };
56683
56684
56685     curtain.cut = function(datum, duration) {
56686         darkness.datum(datum)
56687             .interrupt();
56688
56689         (duration === 0 ? darkness : darkness.transition().duration(duration || 600))
56690             .attr('d', function(d) {
56691                 var string = 'M 0,0 L 0,' + window.innerHeight + ' L ' +
56692                     window.innerWidth + ',' + window.innerHeight + 'L' +
56693                     window.innerWidth + ',0 Z';
56694
56695                 if (!d) return string;
56696                 return string + 'M' +
56697                     d.left + ',' + d.top + 'L' +
56698                     d.left + ',' + (d.top + d.height) + 'L' +
56699                     (d.left + d.width) + ',' + (d.top + d.height) + 'L' +
56700                     (d.left + d.width) + ',' + (d.top) + 'Z';
56701
56702             });
56703     };
56704
56705
56706     curtain.remove = function() {
56707         surface.remove();
56708         tooltip.remove();
56709     };
56710
56711
56712     return utilRebind(curtain, dispatch$$1, 'on');
56713 }
56714
56715 var dataIntroGraph = {"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"]}};
56716
56717 function pointBox(point, context) {
56718     var rect = context.surfaceRect();
56719     point = context.projection(point);
56720     return {
56721         left: point[0] + rect.left - 30,
56722         top: point[1] + rect.top - 50,
56723         width: 60,
56724         height: 70
56725      };
56726 }
56727
56728
56729 function pad$1(box, padding, context) {
56730     if (box instanceof Array) {
56731         var rect = context.surfaceRect();
56732         box = context.projection(box);
56733         box = {
56734             left: box[0] + rect.left,
56735             top: box[1] + rect.top
56736         };
56737     }
56738     return {
56739         left: box.left - padding,
56740         top: box.top - padding,
56741         width: (box.width || 0) + 2 * padding,
56742         height: (box.width || 0) + 2 * padding
56743     };
56744 }
56745
56746
56747 function icon(name, svgklass) {
56748     return '<svg class="icon ' + (svgklass || '') + '">' +
56749          '<use xlink:href="' + name + '"></use></svg>';
56750  }
56751
56752 function uiIntroNavigation(context, reveal) {
56753     var dispatch$$1 = dispatch('done'),
56754         timeouts = [];
56755
56756     var step = {
56757         title: 'intro.navigation.title'
56758     };
56759
56760
56761     function set$$1(f, t$$1) {
56762         timeouts.push(window.setTimeout(f, t$$1));
56763     }
56764
56765
56766     function eventCancel() {
56767         event.stopPropagation();
56768         event.preventDefault();
56769     }
56770
56771
56772     step.enter = function() {
56773         var rect = context.surfaceRect(),
56774             map$$1 = {
56775                 left: rect.left + 10,
56776                 top: rect.top + 70,
56777                 width: rect.width - 70,
56778                 height: rect.height - 170
56779             };
56780
56781         context.map().centerZoom([-85.63591, 41.94285], 19);
56782
56783         reveal(map$$1, t('intro.navigation.drag'));
56784
56785         context.map().on('move.intro', lodash.debounce(function() {
56786             context.map().on('move.intro', null);
56787             townhall();
56788             context.on('enter.intro', inspectTownHall);
56789         }, 400));
56790
56791
56792         function townhall() {
56793             var hall = [-85.63645945147184, 41.942986488012565];
56794             var point = context.projection(hall);
56795
56796             if (point[0] < 0 || point[0] > rect.width ||
56797                 point[1] < 0 || point[1] > rect.height) {
56798                 context.map().center(hall);
56799             }
56800
56801             var box = pointBox(hall, context);
56802             reveal(box, t('intro.navigation.select'));
56803
56804             context.map().on('move.intro', function() {
56805                 var box = pointBox(hall, context);
56806                 reveal(box, t('intro.navigation.select'), {duration: 0});
56807             });
56808         }
56809
56810
56811         function inspectTownHall(mode) {
56812             if (mode.id !== 'select') return;
56813             context.on('enter.intro', null);
56814             context.map().on('move.intro', null);
56815             set$$1(function() {
56816                 reveal('.entity-editor-pane',
56817                     t('intro.navigation.pane', { button: icon('#icon-close', 'pre-text') }));
56818                 context.on('exit.intro', streetSearch);
56819             }, 700);
56820         }
56821
56822
56823         function streetSearch() {
56824             context.on('exit.intro', null);
56825             reveal('.search-header input',
56826                 t('intro.navigation.search', { name: t('intro.graph.spring_st') }));
56827             select('.search-header input')
56828                 .on('keyup.intro', searchResult);
56829         }
56830
56831
56832         function searchResult() {
56833             var first = select('.feature-list-item:nth-child(0n+2)'),  // skip No Results item
56834                 firstName = first.select('.entity-name'),
56835                 name = t('intro.graph.spring_st');
56836
56837             if (!firstName.empty() && firstName.text() === name) {
56838                 reveal(first.node(), t('intro.navigation.choose', { name: name }));
56839                 context.on('exit.intro', selectedStreet);
56840                 select('.search-header input')
56841                     .on('keydown.intro', eventCancel, true)
56842                     .on('keyup.intro', null);
56843             }
56844         }
56845
56846
56847         function selectedStreet() {
56848             var springSt = [-85.63585099140167, 41.942506848938926];
56849             context.map().center(springSt);
56850             context.on('exit.intro', function() {
56851                 dispatch$$1.call('done');
56852             });
56853
56854             set$$1(function() {
56855                 reveal('.entity-editor-pane',
56856                     t('intro.navigation.chosen', {
56857                         name: t('intro.graph.spring_st'),
56858                         button: icon('#icon-close', 'pre-text')
56859                     }));
56860             }, 400);
56861         }
56862     };
56863
56864
56865     step.exit = function() {
56866         timeouts.forEach(window.clearTimeout);
56867         context.map().on('move.intro', null);
56868         context.on('enter.intro', null);
56869         context.on('exit.intro', null);
56870         select('.search-header input')
56871             .on('keydown.intro', null)
56872             .on('keyup.intro', null);
56873     };
56874
56875
56876     return utilRebind(step, dispatch$$1, 'on');
56877 }
56878
56879 function uiIntroPoint(context, reveal) {
56880     var dispatch$$1 = dispatch('done'),
56881         timeouts = [];
56882
56883     var step = {
56884         title: 'intro.points.title'
56885     };
56886
56887
56888     function setTimeout(f, t$$1) {
56889         timeouts.push(window.setTimeout(f, t$$1));
56890     }
56891
56892
56893     function eventCancel() {
56894         event.stopPropagation();
56895         event.preventDefault();
56896     }
56897
56898
56899     step.enter = function() {
56900         context.map().centerZoom([-85.63279, 41.94394], 19);
56901         reveal('button.add-point',
56902             t('intro.points.add', { button: icon('#icon-point', 'pre-text') }),
56903             { tooltipClass: 'intro-points-add' });
56904
56905         var corner = [-85.632481,41.944094];
56906
56907         context.on('enter.intro', addPoint);
56908
56909
56910         function addPoint(mode) {
56911             if (mode.id !== 'add-point') return;
56912             context.on('enter.intro', enterSelect);
56913
56914             var pointBox$$1 = pad$1(corner, 150, context);
56915             reveal(pointBox$$1, t('intro.points.place'));
56916
56917             context.map().on('move.intro', function() {
56918                 pointBox$$1 = pad$1(corner, 150, context);
56919                 reveal(pointBox$$1, t('intro.points.place'), {duration: 0});
56920             });
56921         }
56922
56923
56924         function enterSelect(mode) {
56925             if (mode.id !== 'select') return;
56926             context.map().on('move.intro', null);
56927             context.on('enter.intro', null);
56928
56929             setTimeout(function() {
56930                 reveal('.preset-search-input',
56931                     t('intro.points.search', {name: context.presets().item('amenity/cafe').name()}));
56932                 select('.preset-search-input').on('keyup.intro', keySearch);
56933             }, 500);
56934         }
56935
56936
56937         function keySearch() {
56938             var first = select('.preset-list-item:first-child');
56939             if (first.classed('preset-amenity-cafe')) {
56940                 reveal(first.select('.preset-list-button').node(), t('intro.points.choose'));
56941                 utilBindOnce(context.history(), 'change.intro', selectedPreset);
56942                 select('.preset-search-input')
56943                     .on('keydown.intro', eventCancel, true)
56944                     .on('keyup.intro', null);
56945             }
56946         }
56947
56948
56949         function selectedPreset() {
56950             setTimeout(function() {
56951                 reveal('.entity-editor-pane', t('intro.points.describe'), {tooltipClass: 'intro-points-describe'});
56952                 context.history().on('change.intro', closeEditor);
56953                 context.on('exit.intro', selectPoint);
56954             }, 400);
56955         }
56956
56957
56958         function closeEditor() {
56959             select('.preset-search-input').on('keydown.intro', null);
56960             context.history().on('change.intro', null);
56961             reveal('.entity-editor-pane',
56962                 t('intro.points.close', { button: icon('#icon-apply', 'pre-text') }));
56963         }
56964
56965
56966         function selectPoint() {
56967             context.on('exit.intro', null);
56968             context.history().on('change.intro', null);
56969             context.on('enter.intro', enterReselect);
56970
56971             var pointBox$$1 = pad$1(corner, 150, context);
56972             reveal(pointBox$$1, t('intro.points.reselect'));
56973
56974             context.map().on('move.intro', function() {
56975                 pointBox$$1 = pad$1(corner, 150, context);
56976                 reveal(pointBox$$1, t('intro.points.reselect'), {duration: 0});
56977             });
56978         }
56979
56980
56981         function enterReselect(mode) {
56982             if (mode.id !== 'select') return;
56983             context.map().on('move.intro', null);
56984             context.on('enter.intro', null);
56985
56986             setTimeout(function() {
56987                 reveal('.entity-editor-pane',
56988                     t('intro.points.fixname', { button: icon('#icon-apply', 'pre-text') }));
56989                 context.on('exit.intro', deletePoint);
56990             }, 500);
56991         }
56992
56993
56994         function deletePoint() {
56995             context.on('exit.intro', null);
56996             context.on('enter.intro', enterDelete);
56997
56998             var pointBox$$1 = pad$1(corner, 150, context);
56999             reveal(pointBox$$1, t('intro.points.reselect_delete'));
57000
57001             context.map().on('move.intro', function() {
57002                 pointBox$$1 = pad$1(corner, 150, context);
57003                 reveal(pointBox$$1, t('intro.points.reselect_delete'), {duration: 0});
57004             });
57005         }
57006
57007
57008         function enterDelete(mode) {
57009             if (mode.id !== 'select') return;
57010             context.map().on('move.intro', null);
57011             context.on('enter.intro', null);
57012             context.on('exit.intro', deletePoint);
57013             context.map().on('move.intro', deletePoint);
57014             context.history().on('change.intro', deleted);
57015
57016             setTimeout(function() {
57017                 var node = select('.radial-menu-item-delete').node();
57018                 var pointBox$$1 = pad$1(node.getBoundingClientRect(), 50, context);
57019                 reveal(pointBox$$1,
57020                     t('intro.points.delete', { button: icon('#operation-delete', 'pre-text') }));
57021             }, 300);
57022         }
57023
57024
57025         function deleted(changed) {
57026             if (changed.deleted().length) {
57027                 dispatch$$1.call('done');
57028             }
57029         }
57030
57031     };
57032
57033
57034     step.exit = function() {
57035         timeouts.forEach(window.clearTimeout);
57036         context.on('exit.intro', null);
57037         context.on('enter.intro', null);
57038         context.map().on('move.intro', null);
57039         context.history().on('change.intro', null);
57040         select('.preset-search-input')
57041             .on('keyup.intro', null)
57042             .on('keydown.intro', null);
57043     };
57044
57045     return utilRebind(step, dispatch$$1, 'on');
57046 }
57047
57048 function uiIntroArea(context, reveal) {
57049     var dispatch$$1 = dispatch('done'),
57050         timeout$$1;
57051
57052     var step = {
57053         title: 'intro.areas.title'
57054     };
57055
57056
57057     step.enter = function() {
57058         var playground = [-85.63552, 41.94159],
57059             corner = [-85.63565411045074, 41.9417715536927];
57060         context.map().centerZoom(playground, 19);
57061         reveal('button.add-area',
57062             t('intro.areas.add', { button: icon('#icon-area', 'pre-text') }),
57063             { tooltipClass: 'intro-areas-add' });
57064
57065         context.on('enter.intro', addArea);
57066
57067
57068         function addArea(mode) {
57069             if (mode.id !== 'add-area') return;
57070             context.on('enter.intro', drawArea);
57071
57072             var padding = 120 * Math.pow(2, context.map().zoom() - 19);
57073             var pointBox$$1 = pad$1(corner, padding, context);
57074             reveal(pointBox$$1, t('intro.areas.corner'));
57075
57076             context.map().on('move.intro', function() {
57077                 padding = 120 * Math.pow(2, context.map().zoom() - 19);
57078                 pointBox$$1 = pad$1(corner, padding, context);
57079                 reveal(pointBox$$1, t('intro.areas.corner'), {duration: 0});
57080             });
57081         }
57082
57083
57084         function drawArea(mode) {
57085             if (mode.id !== 'draw-area') return;
57086             context.on('enter.intro', enterSelect);
57087
57088             var padding = 150 * Math.pow(2, context.map().zoom() - 19);
57089             var pointBox$$1 = pad$1(playground, padding, context);
57090             reveal(pointBox$$1, t('intro.areas.place'));
57091
57092             context.map().on('move.intro', function() {
57093                 padding = 150 * Math.pow(2, context.map().zoom() - 19);
57094                 pointBox$$1 = pad$1(playground, padding, context);
57095                 reveal(pointBox$$1, t('intro.areas.place'), {duration: 0});
57096             });
57097         }
57098
57099
57100         function enterSelect(mode) {
57101             if (mode.id !== 'select') return;
57102             context.map().on('move.intro', null);
57103             context.on('enter.intro', null);
57104
57105             timeout$$1 = setTimeout(function() {
57106                 reveal('.preset-search-input',
57107                     t('intro.areas.search',
57108                     { name: context.presets().item('leisure/playground').name() }));
57109                 select('.preset-search-input').on('keyup.intro', keySearch);
57110             }, 500);
57111         }
57112
57113
57114         function keySearch() {
57115             var first = select('.preset-list-item:first-child');
57116             if (first.classed('preset-leisure-playground')) {
57117                 reveal(first.select('.preset-list-button').node(), t('intro.areas.choose'));
57118                 utilBindOnce(context.history(), 'change.intro', selectedPreset);
57119                 select('.preset-search-input').on('keyup.intro', null);
57120             }
57121         }
57122
57123
57124         function selectedPreset() {
57125             reveal('.pane',
57126                 t('intro.areas.describe', { button: icon('#icon-apply', 'pre-text') }));
57127             context.on('exit.intro', function() {
57128                 dispatch$$1.call('done');
57129             });
57130         }
57131     };
57132
57133
57134     step.exit = function() {
57135         window.clearTimeout(timeout$$1);
57136         context.on('enter.intro', null);
57137         context.on('exit.intro', null);
57138         context.history().on('change.intro', null);
57139         context.map().on('move.intro', null);
57140         select('.preset-search-input').on('keyup.intro', null);
57141     };
57142
57143
57144     return utilRebind(step, dispatch$$1, 'on');
57145 }
57146
57147 function uiIntroLine(context, reveal) {
57148     var dispatch$$1 = dispatch('done'),
57149         timeouts = [];
57150
57151     var step = {
57152         title: 'intro.lines.title'
57153     };
57154
57155
57156     function timeout$$1(f, t$$1) {
57157         timeouts.push(window.setTimeout(f, t$$1));
57158     }
57159
57160
57161     function eventCancel() {
57162         event.stopPropagation();
57163         event.preventDefault();
57164     }
57165
57166
57167     step.enter = function() {
57168         var centroid = [-85.62830, 41.95699];
57169         var midpoint = [-85.62975395449628, 41.95787501510204];
57170         var start = [-85.6297754121684, 41.95805253325314];
57171         var intersection = [-85.62974496187628, 41.95742515554585];
57172
57173         context.map().centerZoom(start, 18);
57174         reveal('button.add-line',
57175             t('intro.lines.add', { button: icon('#icon-line', 'pre-text') }),
57176             { tooltipClass: 'intro-lines-add' });
57177
57178         context.on('enter.intro', addLine);
57179
57180
57181         function addLine(mode) {
57182             if (mode.id !== 'add-line') return;
57183             context.on('enter.intro', drawLine);
57184
57185             var padding = 150 * Math.pow(2, context.map().zoom() - 18);
57186             var pointBox$$1 = pad$1(start, padding, context);
57187             reveal(pointBox$$1, t('intro.lines.start'));
57188
57189             context.map().on('move.intro', function() {
57190                 padding = 150 * Math.pow(2, context.map().zoom() - 18);
57191                 pointBox$$1 = pad$1(start, padding, context);
57192                 reveal(pointBox$$1, t('intro.lines.start'), {duration: 0});
57193             });
57194         }
57195
57196
57197         function drawLine(mode) {
57198             if (mode.id !== 'draw-line') return;
57199             context.history().on('change.intro', addIntersection);
57200             context.on('enter.intro', retry);
57201
57202             var padding = 300 * Math.pow(2, context.map().zoom() - 19);
57203             var pointBox$$1 = pad$1(midpoint, padding, context);
57204             reveal(pointBox$$1, t('intro.lines.intersect', {name: t('intro.graph.flower_st')}));
57205
57206             context.map().on('move.intro', function() {
57207                 padding = 300 * Math.pow(2, context.map().zoom() - 19);
57208                 pointBox$$1 = pad$1(midpoint, padding, context);
57209                 reveal(pointBox$$1, t('intro.lines.intersect', {name: t('intro.graph.flower_st')}), {duration: 0});
57210             });
57211         }
57212
57213
57214         // ended line before creating intersection
57215         function retry(mode) {
57216             if (mode.id !== 'select') return;
57217             var pointBox$$1 = pad$1(intersection, 30, context),
57218                 ids = mode.selectedIDs();
57219             reveal(pointBox$$1, t('intro.lines.restart', {name: t('intro.graph.flower_st')}));
57220             select(window).on('mousedown.intro', eventCancel, true);
57221
57222             timeout$$1(function() {
57223                 context.replace(actionDeleteMultiple(ids));
57224                 step.exit();
57225                 step.enter();
57226             }, 3000);
57227         }
57228
57229
57230         function addIntersection(changes) {
57231             if ( lodash.some(changes.created(), function(d) {
57232                 return d.type === 'node' && context.graph().parentWays(d).length > 1;
57233             })) {
57234                 context.history().on('change.intro', null);
57235                 context.on('enter.intro', enterSelect);
57236
57237                 var padding = 900 * Math.pow(2, context.map().zoom() - 19);
57238                 var pointBox$$1 = pad$1(centroid, padding, context);
57239                 reveal(pointBox$$1, t('intro.lines.finish'));
57240
57241                 context.map().on('move.intro', function() {
57242                     padding = 900 * Math.pow(2, context.map().zoom() - 19);
57243                     pointBox$$1 = pad$1(centroid, padding, context);
57244                     reveal(pointBox$$1, t('intro.lines.finish'), {duration: 0});
57245                 });
57246             }
57247         }
57248
57249
57250         function enterSelect(mode) {
57251             if (mode.id !== 'select') return;
57252             context.map().on('move.intro', null);
57253             context.on('enter.intro', null);
57254             select('#curtain').style('pointer-events', 'all');
57255
57256             presetCategory();
57257         }
57258
57259
57260         function presetCategory() {
57261             timeout$$1(function() {
57262                 select('#curtain').style('pointer-events', 'none');
57263                 var road = select('.preset-category-road .preset-list-button');
57264                 reveal(road.node(), t('intro.lines.road'));
57265                 utilBindOnce(road, 'click.intro', roadCategory);
57266             }, 500);
57267         }
57268
57269
57270         function roadCategory() {
57271             timeout$$1(function() {
57272                 var grid = select('.subgrid');
57273                 reveal(grid.node(), t('intro.lines.residential'));
57274                 utilBindOnce(grid.selectAll(':not(.preset-highway-residential) .preset-list-button'),
57275                     'click.intro', retryPreset);
57276                 utilBindOnce(grid.selectAll('.preset-highway-residential .preset-list-button'),
57277                     'click.intro', roadDetails);
57278             }, 500);
57279         }
57280
57281
57282         // selected wrong road type
57283         function retryPreset() {
57284             timeout$$1(function() {
57285                 var preset = select('.entity-editor-pane .preset-list-button');
57286                 reveal(preset.node(), t('intro.lines.wrong_preset'));
57287                 utilBindOnce(preset, 'click.intro', presetCategory);
57288             }, 500);
57289         }
57290
57291
57292         function roadDetails() {
57293             reveal('.pane',
57294                 t('intro.lines.describe', { button: icon('#icon-apply', 'pre-text') }));
57295             context.on('exit.intro', function() {
57296                 dispatch$$1.call('done');
57297             });
57298         }
57299     };
57300
57301
57302     step.exit = function() {
57303         select(window).on('mousedown.intro', null, true);
57304         select('#curtain').style('pointer-events', 'none');
57305         timeouts.forEach(window.clearTimeout);
57306         context.on('enter.intro', null);
57307         context.on('exit.intro', null);
57308         context.map().on('move.intro', null);
57309         context.history().on('change.intro', null);
57310     };
57311
57312     return utilRebind(step, dispatch$$1, 'on');
57313 }
57314
57315 function uiIntroStartEditing(context, reveal) {
57316     var dispatch$$1 = dispatch('done', 'startEditing'),
57317         modalSelection,
57318         timeouts = [];
57319
57320     var step = {
57321         title: 'intro.startediting.title'
57322     };
57323
57324
57325     function timeout$$1(f, t$$1) {
57326         timeouts.push(window.setTimeout(f, t$$1));
57327     }
57328
57329
57330     step.enter = function() {
57331         reveal('.map-control.help-control',
57332             t('intro.startediting.help', { button: icon('#icon-help', 'pre-text') }));
57333
57334         timeout$$1(function() {
57335             reveal('#bar button.save', t('intro.startediting.save'));
57336         }, 5000);
57337
57338         timeout$$1(function() {
57339             reveal('#surface');
57340         }, 10000);
57341
57342         timeout$$1(function() {
57343             modalSelection = uiModal(context.container());
57344
57345             modalSelection.select('.modal')
57346                 .attr('class', 'modal-splash modal col6');
57347
57348             modalSelection.selectAll('.close').remove();
57349
57350             var startbutton = modalSelection.select('.content')
57351                 .attr('class', 'fillL')
57352                 .append('button')
57353                     .attr('class', 'modal-section huge-modal-button')
57354                     .on('click', function() {
57355                         modalSelection.remove();
57356                     });
57357
57358                 startbutton
57359                     .append('div')
57360                     .attr('class','illustration');
57361
57362                 startbutton
57363                     .append('h2')
57364                     .text(t('intro.startediting.start'));
57365
57366             dispatch$$1.call('startEditing');
57367         }, 10500);
57368     };
57369
57370
57371     step.exit = function() {
57372         if (modalSelection) { modalSelection.remove(); }
57373         timeouts.forEach(window.clearTimeout);
57374     };
57375
57376
57377     return utilRebind(step, dispatch$$1, 'on');
57378 }
57379
57380 var sampleIntros = {
57381     navigation: uiIntroNavigation,
57382     point: uiIntroPoint,
57383     area: uiIntroArea,
57384     line: uiIntroLine,
57385     startEditing: uiIntroStartEditing
57386 };
57387
57388
57389 function uiIntro(context) {
57390     var step;
57391
57392     function localizedName(id) {
57393         var features = {
57394             n2140018997: 'city_hall',
57395             n367813436: 'fire_department',
57396             w203988286: 'memory_isle_park',
57397             w203972937: 'riverwalk_trail',
57398             w203972938: 'riverwalk_trail',
57399             w203972940: 'riverwalk_trail',
57400             w41785752: 'w_michigan_ave',
57401             w134150789: 'w_michigan_ave',
57402             w134150795: 'w_michigan_ave',
57403             w134150800: 'w_michigan_ave',
57404             w134150811: 'w_michigan_ave',
57405             w134150802: 'e_michigan_ave',
57406             w134150836: 'e_michigan_ave',
57407             w41074896: 'e_michigan_ave',
57408             w17965834: 'spring_st',
57409             w203986457: 'scidmore_park',
57410             w203049587: 'petting_zoo',
57411             w17967397: 'n_andrews_st',
57412             w17967315: 's_andrews_st',
57413             w17967326: 'n_constantine_st',
57414             w17966400: 's_constantine_st',
57415             w170848823: 'rocky_river',
57416             w170848824: 'rocky_river',
57417             w170848331: 'rocky_river',
57418             w17967752: 'railroad_dr',
57419             w17965998: 'conrail_rr',
57420             w134150845: 'conrail_rr',
57421             w170989131: 'st_joseph_river',
57422             w143497377: 'n_main_st',
57423             w134150801: 's_main_st',
57424             w134150830: 's_main_st',
57425             w17966462: 's_main_st',
57426             w17967734: 'water_st',
57427             w17964996: 'foster_st',
57428             w170848330: 'portage_river',
57429             w17965351: 'flower_st',
57430             w17965502: 'elm_st',
57431             w17965402: 'walnut_st',
57432             w17964793: 'morris_ave',
57433             w17967444: 'east_st',
57434             w17966984: 'portage_ave'
57435         };
57436
57437         return features[id] && t('intro.graph.' + features[id]);
57438     }
57439
57440
57441     var introGraph = {};
57442
57443     for (var key in dataIntroGraph) {
57444         introGraph[key] = osmEntity$$1(dataIntroGraph[key]);
57445         var name = localizedName(key);
57446         if (name) {
57447             introGraph[key].tags.name = name;
57448         }
57449     }
57450
57451
57452     function intro(selection$$1) {
57453         context.enter(modeBrowse$$1(context));
57454
57455         // Save current map state
57456         var history = context.history().toJSON(),
57457             hash = window.location.hash,
57458             center = context.map().center(),
57459             zoom$$1 = context.map().zoom(),
57460             background = context.background().baseLayerSource(),
57461             opacity = selectAll('#map .layer-background').style('opacity'),
57462             loadedTiles = context.connection().loadedTiles(),
57463             baseEntities = context.history().graph().base().entities;
57464
57465         // Block saving
57466         context.inIntro(true);
57467
57468         // Load semi-real data used in intro
57469         context.connection().toggle(false).reset();
57470         context.history().reset();
57471
57472         context.history().merge(values(coreGraph$$1().load(introGraph).entities));
57473         context.background().bing();
57474
57475         selectAll('#map .layer-background').style('opacity', 1);
57476
57477         var curtain = d3curtain();
57478         selection$$1.call(curtain);
57479
57480
57481         function reveal(box, text$$1, options) {
57482             options = options || {};
57483             curtain.reveal(box,
57484                 text$$1 || '',
57485                 options.tooltipClass || '',
57486                 options.duration
57487             );
57488         }
57489
57490         var steps = ['navigation', 'point', 'area', 'line', 'startEditing'].map(function(step, i) {
57491             var s = sampleIntros[step](context, reveal)
57492                 .on('done', function() {
57493                     entered.filter(function(d) {
57494                         return d.title === s.title;
57495                     }).classed('finished', true);
57496                     enter(steps[i + 1]);
57497                 });
57498             return s;
57499         });
57500
57501         steps[steps.length - 1].on('startEditing', function() {
57502             curtain.remove();
57503             navwrap.remove();
57504             selectAll('#map .layer-background').style('opacity', opacity);
57505             context.connection().toggle(true).reset().loadedTiles(loadedTiles);
57506             context.history().reset().merge(values(baseEntities));
57507             context.background().baseLayerSource(background);
57508             if (history) context.history().fromJSON(history, false);
57509             context.map().centerZoom(center, zoom$$1);
57510             window.location.replace(hash);
57511             context.inIntro(false);
57512         });
57513
57514         var navwrap = selection$$1
57515             .append('div')
57516             .attr('class', 'intro-nav-wrap fillD');
57517
57518         var buttonwrap = navwrap
57519             .append('div')
57520             .attr('class', 'joined')
57521             .selectAll('button.step');
57522
57523         var entered = buttonwrap
57524             .data(steps)
57525             .enter()
57526             .append('button')
57527             .attr('class', 'step')
57528             .on('click', enter);
57529
57530         entered
57531             .append('label')
57532             .text(function(d) { return t(d.title); });
57533
57534         entered
57535             .append('span')
57536             .attr('class', 'status')
57537             .text(' - ' + t('intro.done'));
57538
57539         enter(steps[0]);
57540
57541
57542         function enter(newStep) {
57543             if (step) { step.exit(); }
57544
57545             context.enter(modeBrowse$$1(context));
57546
57547             step = newStep;
57548             step.enter();
57549
57550             entered.classed('active', function(d) {
57551                 return d.title === step.title;
57552             });
57553         }
57554
57555     }
57556
57557
57558     return intro;
57559 }
57560
57561 function uiHelp(context) {
57562     var key = 'H';
57563
57564     var docKeys = [
57565         'help.help',
57566         'help.editing_saving',
57567         'help.roads',
57568         'help.gps',
57569         'help.imagery',
57570         'help.addresses',
57571         'help.inspector',
57572         'help.buildings',
57573         'help.relations'];
57574
57575     var docs = docKeys.map(function(key) {
57576         var text$$1 = t(key);
57577         return {
57578             title: text$$1.split('\n')[0].replace('#', '').trim(),
57579             html: marked(text$$1.split('\n').slice(1).join('\n'))
57580         };
57581     });
57582
57583
57584     function help(selection$$1) {
57585
57586         function hide() {
57587             setVisible(false);
57588         }
57589
57590
57591         function toggle() {
57592             if (event) event.preventDefault();
57593             tooltipBehavior.hide(button);
57594             setVisible(!button.classed('active'));
57595         }
57596
57597
57598         function setVisible(show) {
57599             if (show !== shown) {
57600                 button.classed('active', show);
57601                 shown = show;
57602
57603                 if (show) {
57604                     selection$$1.on('mousedown.help-inside', function() {
57605                         return event.stopPropagation();
57606                     });
57607                     pane.style('display', 'block')
57608                         .style('right', '-500px')
57609                         .transition()
57610                         .duration(200)
57611                         .style('right', '0px');
57612                 } else {
57613                     pane.style('right', '0px')
57614                         .transition()
57615                         .duration(200)
57616                         .style('right', '-500px')
57617                         .on('end', function() {
57618                             select(this).style('display', 'none');
57619                         });
57620                     selection$$1.on('mousedown.help-inside', null);
57621                 }
57622             }
57623         }
57624
57625
57626         function clickHelp(d, i) {
57627             pane.property('scrollTop', 0);
57628             doctitle.html(d.title);
57629             body.html(d.html);
57630             body.selectAll('a')
57631                 .attr('target', '_blank');
57632             menuItems.classed('selected', function(m) {
57633                 return m.title === d.title;
57634             });
57635
57636             nav.html('');
57637
57638             if (i > 0) {
57639                 var prevLink = nav.append('a')
57640                     .attr('class', 'previous')
57641                     .on('click', function() {
57642                         clickHelp(docs[i - 1], i - 1);
57643                     });
57644                 prevLink.append('span').html('&#9668; ' + docs[i - 1].title);
57645             }
57646             if (i < docs.length - 1) {
57647                 var nextLink = nav.append('a')
57648                     .attr('class', 'next')
57649                     .on('click', function() {
57650                         clickHelp(docs[i + 1], i + 1);
57651                     });
57652                 nextLink.append('span').html(docs[i + 1].title + ' &#9658;');
57653             }
57654         }
57655
57656
57657         function clickWalkthrough() {
57658             select(document.body).call(uiIntro(context));
57659             setVisible(false);
57660         }
57661
57662
57663         var pane = selection$$1.append('div')
57664                 .attr('class', 'help-wrap map-overlay fillL col5 content hide'),
57665             tooltipBehavior = tooltip()
57666                 .placement((textDirection === 'rtl') ? 'right' : 'left')
57667                 .html(true)
57668                 .title(uiTooltipHtml(t('help.title'), key)),
57669             button = selection$$1.append('button')
57670                 .attr('tabindex', -1)
57671                 .on('click', toggle)
57672                 .call(svgIcon('#icon-help', 'light'))
57673                 .call(tooltipBehavior),
57674             shown = false;
57675
57676
57677         var toc = pane.append('ul')
57678             .attr('class', 'toc');
57679
57680         var menuItems = toc.selectAll('li')
57681             .data(docs)
57682             .enter()
57683             .append('li')
57684             .append('a')
57685             .html(function(d) { return d.title; })
57686             .on('click', clickHelp);
57687
57688         toc.append('li')
57689             .attr('class','walkthrough')
57690             .append('a')
57691             .text(t('splash.walkthrough'))
57692             .on('click', clickWalkthrough);
57693
57694         var content = pane.append('div')
57695             .attr('class', 'left-content');
57696
57697         var doctitle = content.append('h2')
57698             .text(t('help.title'));
57699
57700         var body = content.append('div')
57701             .attr('class', 'body');
57702
57703         var nav = content.append('div')
57704             .attr('class', 'nav');
57705
57706         clickHelp(docs[0], 0);
57707
57708         var keybinding = d3keybinding('help')
57709             .on(key, toggle)
57710             .on('B', hide)
57711             .on('F', hide);
57712
57713         select(document)
57714             .call(keybinding);
57715
57716         context.surface().on('mousedown.help-outside', hide);
57717         context.container().on('mousedown.help-outside', hide);
57718     }
57719
57720     return help;
57721 }
57722
57723 function uiInfo(context) {
57724     var key = uiCmd('⌘I'),
57725         isImperial = (utilDetect().locale.toLowerCase() === 'en-us'),
57726         isHidden = true;
57727
57728
57729     function info(selection$$1) {
57730
57731         function radiansToMeters(r) {
57732             // using WGS84 authalic radius (6371007.1809 m)
57733             return r * 6371007.1809;
57734         }
57735
57736         function steradiansToSqmeters(r) {
57737             // http://gis.stackexchange.com/a/124857/40446
57738             return r / (4 * Math.PI) * 510065621724000;
57739         }
57740
57741
57742         function toLineString(feature) {
57743             if (feature.type === 'LineString') return feature;
57744
57745             var result = { type: 'LineString', coordinates: [] };
57746             if (feature.type === 'Polygon') {
57747                 result.coordinates = feature.coordinates[0];
57748             } else if (feature.type === 'MultiPolygon') {
57749                 result.coordinates = feature.coordinates[0][0];
57750             }
57751
57752             return result;
57753         }
57754
57755
57756         function displayLength(m) {
57757             var d = m * (isImperial ? 3.28084 : 1),
57758                 p, unit;
57759
57760             if (isImperial) {
57761                 if (d >= 5280) {
57762                     d /= 5280;
57763                     unit = 'mi';
57764                 } else {
57765                     unit = 'ft';
57766                 }
57767             } else {
57768                 if (d >= 1000) {
57769                     d /= 1000;
57770                     unit = 'km';
57771                 } else {
57772                     unit = 'm';
57773                 }
57774             }
57775
57776             // drop unnecessary precision
57777             p = d > 1000 ? 0 : d > 100 ? 1 : 2;
57778
57779             return String(d.toFixed(p)) + ' ' + unit;
57780         }
57781
57782
57783         function displayArea(m2) {
57784             var d = m2 * (isImperial ? 10.7639111056 : 1),
57785                 d1, d2, p1, p2, unit1, unit2;
57786
57787             if (isImperial) {
57788                 if (d >= 6969600) {     // > 0.25mi² show mi²
57789                     d1 = d / 27878400;
57790                     unit1 = 'mi²';
57791                 } else {
57792                     d1 = d;
57793                     unit1 = 'ft²';
57794                 }
57795
57796                 if (d > 4356 && d < 43560000) {   // 0.1 - 1000 acres
57797                     d2 = d / 43560;
57798                     unit2 = 'ac';
57799                 }
57800
57801             } else {
57802                 if (d >= 250000) {    // > 0.25km² show km²
57803                     d1 = d / 1000000;
57804                     unit1 = 'km²';
57805                 } else {
57806                     d1 = d;
57807                     unit1 = 'm²';
57808                 }
57809
57810                 if (d > 1000 && d < 10000000) {   // 0.1 - 1000 hectares
57811                     d2 = d / 10000;
57812                     unit2 = 'ha';
57813                 }
57814             }
57815
57816             // drop unnecessary precision
57817             p1 = d1 > 1000 ? 0 : d1 > 100 ? 1 : 2;
57818             p2 = d2 > 1000 ? 0 : d2 > 100 ? 1 : 2;
57819
57820             return String(d1.toFixed(p1)) + ' ' + unit1 +
57821                 (d2 ? ' (' + String(d2.toFixed(p2)) + ' ' + unit2 + ')' : '');
57822         }
57823
57824
57825         function redraw() {
57826             if (isHidden) return;
57827
57828             var resolver = context.graph(),
57829                 selected = lodash.filter(context.selectedIDs(), function(e) { return context.hasEntity(e); }),
57830                 singular = selected.length === 1 ? selected[0] : null,
57831                 extent$$1 = geoExtent$$1(),
57832                 entity;
57833
57834             wrap.html('');
57835             wrap.append('h4')
57836                 .attr('class', 'infobox-heading fillD')
57837                 .text(singular || t('infobox.selected', { n: selected.length }));
57838
57839             if (!selected.length) return;
57840
57841             var center;
57842             for (var i = 0; i < selected.length; i++) {
57843                 entity = context.entity(selected[i]);
57844                 extent$$1._extend(entity.extent(resolver));
57845             }
57846             center = extent$$1.center();
57847
57848
57849             var list = wrap.append('ul');
57850
57851             // multiple features, just display extent center..
57852             if (!singular) {
57853                 list.append('li')
57854                     .text(t('infobox.center') + ': ' + center[0].toFixed(5) + ', ' + center[1].toFixed(5));
57855                 return;
57856             }
57857
57858             // single feature, display details..
57859             if (!entity) return;
57860             var geometry = entity.geometry(resolver);
57861
57862             if (geometry === 'line' || geometry === 'area') {
57863                 var closed = (entity.type === 'relation') || (entity.isClosed() && !entity.isDegenerate()),
57864                     feature = entity.asGeoJSON(resolver),
57865                     length = radiansToMeters(d3GeoLength(toLineString(feature))),
57866                     lengthLabel = t('infobox.' + (closed ? 'perimeter' : 'length')),
57867                     centroid = d3GeoCentroid(feature);
57868
57869                 list.append('li')
57870                     .text(t('infobox.geometry') + ': ' +
57871                         (closed ? t('infobox.closed') + ' ' : '') + t('geometry.' + geometry) );
57872
57873                 if (closed) {
57874                     var area$$1 = steradiansToSqmeters(entity.area(resolver));
57875                     list.append('li')
57876                         .text(t('infobox.area') + ': ' + displayArea(area$$1));
57877                 }
57878
57879                 list.append('li')
57880                     .text(lengthLabel + ': ' + displayLength(length));
57881
57882                 list.append('li')
57883                     .text(t('infobox.centroid') + ': ' + centroid[0].toFixed(5) + ', ' + centroid[1].toFixed(5));
57884
57885
57886                 var toggle  = isImperial ? 'imperial' : 'metric';
57887                 wrap.append('a')
57888                     .text(t('infobox.' + toggle))
57889                     .attr('href', '#')
57890                     .attr('class', 'button')
57891                     .on('click', function() {
57892                         event.preventDefault();
57893                         isImperial = !isImperial;
57894                         redraw();
57895                     });
57896
57897             } else {
57898                 var centerLabel = t('infobox.' + (entity.type === 'node' ? 'location' : 'center'));
57899
57900                 list.append('li')
57901                     .text(t('infobox.geometry') + ': ' + t('geometry.' + geometry));
57902
57903                 list.append('li')
57904                     .text(centerLabel + ': ' + center[0].toFixed(5) + ', ' + center[1].toFixed(5));
57905             }
57906         }
57907
57908
57909         function toggle() {
57910             if (event) {
57911                 event.preventDefault();
57912             }
57913
57914             isHidden = !isHidden;
57915
57916             if (isHidden) {
57917                 wrap
57918                     .style('display', 'block')
57919                     .style('opacity', 1)
57920                     .transition()
57921                     .duration(200)
57922                     .style('opacity', 0)
57923                     .on('end', function() {
57924                         select(this).style('display', 'none');
57925                     });
57926             } else {
57927                 wrap
57928                     .style('display', 'block')
57929                     .style('opacity', 0)
57930                     .transition()
57931                     .duration(200)
57932                     .style('opacity', 1)
57933                     .on('end', function() {
57934                         redraw();
57935                     });
57936             }
57937         }
57938
57939
57940         var wrap = selection$$1.selectAll('.infobox')
57941             .data([0]);
57942
57943         wrap = wrap.enter()
57944             .append('div')
57945             .attr('class', 'infobox fillD2')
57946             .style('display', (isHidden ? 'none' : 'block'))
57947             .merge(wrap);
57948
57949         context.map()
57950             .on('drawn.info', redraw);
57951
57952         redraw();
57953
57954         var keybinding = d3keybinding('info')
57955             .on(key, toggle);
57956
57957         select(document)
57958             .call(keybinding);
57959     }
57960
57961     return info;
57962 }
57963
57964 function uiMapData(context) {
57965     var key = 'F',
57966         features = context.features().keys(),
57967         layers = context.layers(),
57968         fills = ['wireframe', 'partial', 'full'],
57969         fillDefault = context.storage('area-fill') || 'partial',
57970         fillSelected = fillDefault;
57971
57972
57973     function map_data(selection$$1) {
57974
57975         function showsFeature(d) {
57976             return context.features().enabled(d);
57977         }
57978
57979
57980         function autoHiddenFeature(d) {
57981             return context.features().autoHidden(d);
57982         }
57983
57984
57985         function clickFeature(d) {
57986             context.features().toggle(d);
57987             update();
57988         }
57989
57990
57991         function showsFill(d) {
57992             return fillSelected === d;
57993         }
57994
57995
57996         function setFill(d) {
57997             lodash.each(fills, function(opt) {
57998                 context.surface().classed('fill-' + opt, Boolean(opt === d));
57999             });
58000
58001             fillSelected = d;
58002             if (d !== 'wireframe') {
58003                 fillDefault = d;
58004                 context.storage('area-fill', d);
58005             }
58006             update();
58007         }
58008
58009
58010         function showsLayer(which) {
58011             var layer = layers.layer(which);
58012             if (layer) {
58013                 return layer.enabled();
58014             }
58015             return false;
58016         }
58017
58018
58019         function setLayer(which, enabled) {
58020             var layer = layers.layer(which);
58021             if (layer) {
58022                 layer.enabled(enabled);
58023                 update();
58024             }
58025         }
58026
58027
58028         function toggleLayer(which) {
58029             setLayer(which, !showsLayer(which));
58030         }
58031
58032
58033         function clickGpx() {
58034             toggleLayer('gpx');
58035         }
58036
58037
58038         function clickMapillaryImages() {
58039             toggleLayer('mapillary-images');
58040             if (!showsLayer('mapillary-images')) {
58041                 setLayer('mapillary-signs', false);
58042             }
58043         }
58044
58045
58046         function clickMapillarySigns() {
58047             toggleLayer('mapillary-signs');
58048         }
58049
58050
58051         function drawMapillaryItems(selection$$1) {
58052             var mapillaryImages = layers.layer('mapillary-images'),
58053                 mapillarySigns = layers.layer('mapillary-signs'),
58054                 supportsMapillaryImages = mapillaryImages && mapillaryImages.supported(),
58055                 supportsMapillarySigns = mapillarySigns && mapillarySigns.supported(),
58056                 showsMapillaryImages = supportsMapillaryImages && mapillaryImages.enabled(),
58057                 showsMapillarySigns = supportsMapillarySigns && mapillarySigns.enabled();
58058
58059             var mapillaryList = selection$$1
58060                 .selectAll('.layer-list-mapillary')
58061                 .data([0]);
58062
58063             mapillaryList = mapillaryList.enter()
58064                 .append('ul')
58065                 .attr('class', 'layer-list layer-list-mapillary')
58066                 .merge(mapillaryList);
58067
58068
58069             var mapillaryImageLayerItem = mapillaryList
58070                 .selectAll('.list-item-mapillary-images')
58071                 .data(supportsMapillaryImages ? [0] : []);
58072
58073             mapillaryImageLayerItem.exit()
58074                 .remove();
58075
58076             var enterImages = mapillaryImageLayerItem.enter()
58077                 .append('li')
58078                 .attr('class', 'list-item-mapillary-images');
58079
58080             var labelImages = enterImages
58081                 .append('label')
58082                 .call(tooltip()
58083                     .title(t('mapillary_images.tooltip'))
58084                     .placement('top'));
58085
58086             labelImages
58087                 .append('input')
58088                 .attr('type', 'checkbox')
58089                 .on('change', clickMapillaryImages);
58090
58091             labelImages
58092                 .append('span')
58093                 .text(t('mapillary_images.title'));
58094
58095
58096             var mapillarySignLayerItem = mapillaryList
58097                 .selectAll('.list-item-mapillary-signs')
58098                 .data(supportsMapillarySigns ? [0] : []);
58099
58100             mapillarySignLayerItem.exit()
58101                 .remove();
58102
58103             var enterSigns = mapillarySignLayerItem.enter()
58104                 .append('li')
58105                 .attr('class', 'list-item-mapillary-signs');
58106
58107             var labelSigns = enterSigns
58108                 .append('label')
58109                 .call(tooltip()
58110                     .title(t('mapillary_signs.tooltip'))
58111                     .placement('top'));
58112
58113             labelSigns
58114                 .append('input')
58115                 .attr('type', 'checkbox')
58116                 .on('change', clickMapillarySigns);
58117
58118             labelSigns
58119                 .append('span')
58120                 .text(t('mapillary_signs.title'));
58121
58122
58123             // Updates
58124             mapillaryImageLayerItem = mapillaryImageLayerItem
58125                 .merge(enterImages);
58126
58127             mapillaryImageLayerItem
58128                 .classed('active', showsMapillaryImages)
58129                 .selectAll('input')
58130                 .property('checked', showsMapillaryImages);
58131
58132
58133             mapillarySignLayerItem = mapillarySignLayerItem
58134                 .merge(enterSigns);
58135
58136             mapillarySignLayerItem
58137                 .classed('active', showsMapillarySigns)
58138                 .selectAll('input')
58139                 .property('disabled', !showsMapillaryImages)
58140                 .property('checked', showsMapillarySigns);
58141
58142             mapillarySignLayerItem
58143                 .selectAll('label')
58144                 .classed('deemphasize', !showsMapillaryImages);
58145         }
58146
58147
58148         function drawGpxItem(selection$$1) {
58149             var gpx = layers.layer('gpx'),
58150                 hasGpx = gpx && gpx.hasGpx(),
58151                 showsGpx = hasGpx && gpx.enabled();
58152
58153             var gpxLayerItem = selection$$1
58154                 .selectAll('.layer-list-gpx')
58155                 .data(gpx ? [0] : []);
58156
58157             // Exit
58158             gpxLayerItem.exit()
58159                 .remove();
58160
58161             // Enter
58162             var enter = gpxLayerItem.enter()
58163                 .append('ul')
58164                 .attr('class', 'layer-list layer-list-gpx')
58165                 .append('li')
58166                 .classed('list-item-gpx', true);
58167
58168             enter
58169                 .append('button')
58170                 .attr('class', 'list-item-gpx-extent')
58171                 .call(tooltip()
58172                     .title(t('gpx.zoom'))
58173                     .placement((textDirection === 'rtl') ? 'right' : 'left'))
58174                 .on('click', function() {
58175                     event.preventDefault();
58176                     event.stopPropagation();
58177                     gpx.fitZoom();
58178                 })
58179                 .call(svgIcon('#icon-search'));
58180
58181             enter
58182                 .append('button')
58183                 .attr('class', 'list-item-gpx-browse')
58184                 .call(tooltip()
58185                     .title(t('gpx.browse'))
58186                     .placement((textDirection === 'rtl') ? 'right' : 'left'))
58187                 .on('click', function() {
58188                     select(document.createElement('input'))
58189                         .attr('type', 'file')
58190                         .on('change', function() {
58191                             gpx.files(event.target.files);
58192                         })
58193                         .node().click();
58194                 })
58195                 .call(svgIcon('#icon-geolocate'));
58196
58197             var labelGpx = enter
58198                 .append('label')
58199                 .call(tooltip().title(t('gpx.drag_drop')).placement('top'));
58200
58201             labelGpx
58202                 .append('input')
58203                 .attr('type', 'checkbox')
58204                 .on('change', clickGpx);
58205
58206             labelGpx
58207                 .append('span')
58208                 .text(t('gpx.local_layer'));
58209
58210
58211             // Update
58212             gpxLayerItem = gpxLayerItem
58213                 .merge(enter);
58214
58215             gpxLayerItem
58216                 .classed('active', showsGpx)
58217                 .selectAll('input')
58218                 .property('disabled', !hasGpx)
58219                 .property('checked', showsGpx);
58220
58221             gpxLayerItem
58222                 .selectAll('label')
58223                 .classed('deemphasize', !hasGpx);
58224         }
58225
58226
58227         function drawList(selection$$1, data, type, name, change, active$$1) {
58228             var items = selection$$1.selectAll('li')
58229                 .data(data);
58230
58231             // Exit
58232             items.exit()
58233                 .remove();
58234
58235             // Enter
58236             var enter = items.enter()
58237                 .append('li')
58238                 .attr('class', 'layer')
58239                 .call(tooltip()
58240                     .html(true)
58241                     .title(function(d) {
58242                         var tip = t(name + '.' + d + '.tooltip'),
58243                             key = (d === 'wireframe' ? 'W' : null);
58244
58245                         if (name === 'feature' && autoHiddenFeature(d)) {
58246                             tip += '<div>' + t('map_data.autohidden') + '</div>';
58247                         }
58248                         return uiTooltipHtml(tip, key);
58249                     })
58250                     .placement('top')
58251                 );
58252
58253             var label = enter
58254                 .append('label');
58255
58256             label
58257                 .append('input')
58258                 .attr('type', type)
58259                 .attr('name', name)
58260                 .on('change', change);
58261
58262             label
58263                 .append('span')
58264                 .text(function(d) { return t(name + '.' + d + '.description'); });
58265
58266             // Update
58267             items = items
58268                 .merge(enter);
58269
58270             items
58271                 .classed('active', active$$1)
58272                 .selectAll('input')
58273                 .property('checked', active$$1)
58274                 .property('indeterminate', function(d) {
58275                     return (name === 'feature' && autoHiddenFeature(d));
58276                 });
58277         }
58278
58279
58280         function update() {
58281             dataLayerContainer.call(drawMapillaryItems);
58282             dataLayerContainer.call(drawGpxItem);
58283
58284             fillList.call(drawList, fills, 'radio', 'area_fill', setFill, showsFill);
58285             featureList.call(drawList, features, 'checkbox', 'feature', clickFeature, showsFeature);
58286         }
58287
58288
58289         function hidePanel() {
58290             setVisible(false);
58291         }
58292
58293
58294         function togglePanel() {
58295             if (event) event.preventDefault();
58296             tooltipBehavior.hide(button);
58297             setVisible(!button.classed('active'));
58298         }
58299
58300
58301         function toggleWireframe() {
58302             if (event) {
58303                 event.preventDefault();
58304                 event.stopPropagation();
58305             }
58306             setFill((fillSelected === 'wireframe' ? fillDefault : 'wireframe'));
58307             context.map().pan([0,0]);  // trigger a redraw
58308         }
58309
58310
58311         function setVisible(show) {
58312             if (show !== shown) {
58313                 button.classed('active', show);
58314                 shown = show;
58315
58316                 if (show) {
58317                     update();
58318                     selection$$1.on('mousedown.map_data-inside', function() {
58319                         return event.stopPropagation();
58320                     });
58321                     content.style('display', 'block')
58322                         .style('right', '-300px')
58323                         .transition()
58324                         .duration(200)
58325                         .style('right', '0px');
58326                 } else {
58327                     content.style('display', 'block')
58328                         .style('right', '0px')
58329                         .transition()
58330                         .duration(200)
58331                         .style('right', '-300px')
58332                         .on('end', function() {
58333                             select(this).style('display', 'none');
58334                         });
58335                     selection$$1.on('mousedown.map_data-inside', null);
58336                 }
58337             }
58338         }
58339
58340
58341         var content = selection$$1
58342                 .append('div')
58343                 .attr('class', 'fillL map-overlay col3 content hide'),
58344             tooltipBehavior = tooltip()
58345                 .placement((textDirection === 'rtl') ? 'right' : 'left')
58346                 .html(true)
58347                 .title(uiTooltipHtml(t('map_data.description'), key)),
58348             button = selection$$1
58349                 .append('button')
58350                 .attr('tabindex', -1)
58351                 .on('click', togglePanel)
58352                 .call(svgIcon('#icon-data', 'light'))
58353                 .call(tooltipBehavior),
58354             shown = false;
58355
58356         content
58357             .append('h4')
58358             .text(t('map_data.title'));
58359
58360
58361         // data layers
58362         content
58363             .append('a')
58364             .text(t('map_data.data_layers'))
58365             .attr('href', '#')
58366             .classed('hide-toggle', true)
58367             .classed('expanded', true)
58368             .on('click', function() {
58369                 var exp = select(this).classed('expanded');
58370                 dataLayerContainer.style('display', exp ? 'none' : 'block');
58371                 select(this).classed('expanded', !exp);
58372                 event.preventDefault();
58373             });
58374
58375         var dataLayerContainer = content
58376             .append('div')
58377             .attr('class', 'data-data-layers')
58378             .style('display', 'block');
58379
58380
58381         // area fills
58382         content
58383             .append('a')
58384             .text(t('map_data.fill_area'))
58385             .attr('href', '#')
58386             .classed('hide-toggle', true)
58387             .classed('expanded', false)
58388             .on('click', function() {
58389                 var exp = select(this).classed('expanded');
58390                 fillContainer.style('display', exp ? 'none' : 'block');
58391                 select(this).classed('expanded', !exp);
58392                 event.preventDefault();
58393             });
58394
58395         var fillContainer = content
58396             .append('div')
58397             .attr('class', 'data-area-fills')
58398             .style('display', 'none');
58399
58400         var fillList = fillContainer
58401             .append('ul')
58402             .attr('class', 'layer-list layer-fill-list');
58403
58404
58405         // feature filters
58406         content
58407             .append('a')
58408             .text(t('map_data.map_features'))
58409             .attr('href', '#')
58410             .classed('hide-toggle', true)
58411             .classed('expanded', false)
58412             .on('click', function() {
58413                 var exp = select(this).classed('expanded');
58414                 featureContainer.style('display', exp ? 'none' : 'block');
58415                 select(this).classed('expanded', !exp);
58416                 event.preventDefault();
58417             });
58418
58419         var featureContainer = content
58420             .append('div')
58421             .attr('class', 'data-feature-filters')
58422             .style('display', 'none');
58423
58424         var featureList = featureContainer
58425             .append('ul')
58426             .attr('class', 'layer-list layer-feature-list');
58427
58428
58429         context.features()
58430             .on('change.map_data-update', update);
58431
58432         setFill(fillDefault);
58433
58434         var keybinding = d3keybinding('features')
58435             .on(key, togglePanel)
58436             .on('W', toggleWireframe)
58437             .on('B', hidePanel)
58438             .on('H', hidePanel);
58439
58440         select(document)
58441             .call(keybinding);
58442
58443         context.surface().on('mousedown.map_data-outside', hidePanel);
58444         context.container().on('mousedown.map_data-outside', hidePanel);
58445     }
58446
58447
58448     return map_data;
58449 }
58450
58451 function uiModes(context) {
58452     var modes = [
58453         modeAddPoint$$1(context),
58454         modeAddLine$$1(context),
58455         modeAddArea$$1(context)
58456     ];
58457
58458
58459     function editable() {
58460         return context.editable() && context.mode().id !== 'save';
58461     }
58462
58463
58464     return function(selection$$1) {
58465         var buttons = selection$$1.selectAll('button.add-button')
58466             .data(modes);
58467
58468         buttons = buttons.enter()
58469             .append('button')
58470             .attr('tabindex', -1)
58471             .attr('class', function(mode) { return mode.id + ' add-button col4'; })
58472             .on('click.mode-buttons', function(mode) {
58473                 if (mode.id === context.mode().id) {
58474                     context.enter(modeBrowse$$1(context));
58475                 } else {
58476                     context.enter(mode);
58477                 }
58478             })
58479             .call(tooltip()
58480                 .placement('bottom')
58481                 .html(true)
58482                 .title(function(mode) {
58483                     return uiTooltipHtml(mode.description, mode.key);
58484                 })
58485             );
58486
58487         context.map()
58488             .on('move.modes', lodash.debounce(update, 500));
58489
58490         context
58491             .on('enter.modes', update);
58492
58493         buttons
58494             .each(function(d) {
58495                 select(this)
58496                     .call(svgIcon('#icon-' + d.button, 'pre-text'));
58497             });
58498
58499         buttons
58500             .append('span')
58501             .attr('class', 'label')
58502             .text(function(mode) { return mode.title; });
58503
58504         context
58505             .on('enter.editor', function(entered) {
58506                 selection$$1.selectAll('button.add-button')
58507                     .classed('active', function(mode) { return entered.button === mode.button; });
58508                 context.container()
58509                     .classed('mode-' + entered.id, true);
58510             });
58511
58512         context
58513             .on('exit.editor', function(exited) {
58514                 context.container()
58515                     .classed('mode-' + exited.id, false);
58516             });
58517
58518         var keybinding = d3keybinding('mode-buttons');
58519
58520         modes.forEach(function(m) {
58521             keybinding.on(m.key, function() {
58522                 if (editable()) context.enter(m);
58523             });
58524         });
58525
58526         select(document)
58527             .call(keybinding);
58528
58529
58530         function update() {
58531             selection$$1.selectAll('button.add-button')
58532                 .property('disabled', !editable());
58533         }
58534     };
58535 }
58536
58537 function uiRestore(context) {
58538
58539     return function(selection) {
58540         if (!context.history().lock() || !context.history().restorableChanges())
58541             return;
58542
58543         var modalSelection = uiModal(selection, true);
58544
58545         modalSelection.select('.modal')
58546             .attr('class', 'modal fillL col6');
58547
58548         var introModal = modalSelection.select('.content');
58549
58550         introModal
58551             .attr('class','cf');
58552
58553         introModal
58554             .append('div')
58555             .attr('class', 'modal-section')
58556             .append('h3')
58557             .text(t('restore.heading'));
58558
58559         introModal
58560             .append('div')
58561             .attr('class','modal-section')
58562             .append('p')
58563             .text(t('restore.description'));
58564
58565         var buttonWrap = introModal
58566             .append('div')
58567             .attr('class', 'modal-actions cf');
58568
58569         var restore = buttonWrap
58570             .append('button')
58571             .attr('class', 'restore col6')
58572             .text(t('restore.restore'))
58573             .on('click', function() {
58574                 context.history().restore();
58575                 modalSelection.remove();
58576             });
58577
58578         buttonWrap
58579             .append('button')
58580             .attr('class', 'reset col6')
58581             .text(t('restore.reset'))
58582             .on('click', function() {
58583                 context.history().clearSaved();
58584                 modalSelection.remove();
58585             });
58586
58587         restore.node().focus();
58588     };
58589 }
58590
58591 function uiSave(context) {
58592     var history = context.history(),
58593         key = uiCmd('⌘S');
58594
58595
58596     function saving() {
58597         return context.mode().id === 'save';
58598     }
58599
58600
58601     function save() {
58602         event.preventDefault();
58603         if (!context.inIntro() && !saving() && history.hasChanges()) {
58604             context.enter(modeSave$$1(context));
58605         }
58606     }
58607
58608
58609     function getBackground(numChanges) {
58610         var step;
58611         if (numChanges === 0) {
58612             return null;
58613         } else if (numChanges <= 50) {
58614             step = numChanges / 50;
58615             return interpolateRgb('#fff', '#ff8')(step);  // white -> yellow
58616         } else {
58617             step = Math.min((numChanges - 50) / 50, 1.0);
58618             return interpolateRgb('#ff8', '#f88')(step);  // yellow -> red
58619         }
58620     }
58621
58622
58623     return function(selection$$1) {
58624         var tooltipBehavior = tooltip()
58625             .placement('bottom')
58626             .html(true)
58627             .title(uiTooltipHtml(t('save.no_changes'), key));
58628
58629         var button = selection$$1
58630             .append('button')
58631             .attr('class', 'save col12 disabled')
58632             .attr('tabindex', -1)
58633             .on('click', save)
58634             .call(tooltipBehavior);
58635
58636         button
58637             .append('span')
58638             .attr('class', 'label')
58639             .text(t('save.title'));
58640
58641         button
58642             .append('span')
58643             .attr('class', 'count')
58644             .text('0');
58645
58646         var keybinding = d3keybinding('undo-redo')
58647             .on(key, save, true);
58648
58649         select(document)
58650             .call(keybinding);
58651
58652         var numChanges = 0;
58653
58654         context.history()
58655             .on('change.save', function() {
58656                 var _ = history.difference().summary().length;
58657                 if (_ === numChanges)
58658                     return;
58659                 numChanges = _;
58660
58661                 tooltipBehavior.title(uiTooltipHtml(
58662                     t(numChanges > 0 ? 'save.help' : 'save.no_changes'), key));
58663
58664                 var background = getBackground(numChanges);
58665
58666                 button
58667                     .classed('disabled', numChanges === 0)
58668                     .classed('has-count', numChanges > 0)
58669                     .style('background', background);
58670
58671                 button.select('span.count')
58672                     .text(numChanges)
58673                     .style('background', background)
58674                     .style('border-color', background);
58675             });
58676
58677         context
58678             .on('enter.save', function() {
58679                 button.property('disabled', saving());
58680                 if (saving()) button.call(tooltipBehavior.hide);
58681             });
58682     };
58683 }
58684
58685 function uiScale(context) {
58686     var projection = context.projection,
58687         isImperial = (utilDetect().locale.toLowerCase() === 'en-us'),
58688         maxLength = 180,
58689         tickHeight = 8;
58690
58691
58692     function scaleDefs(loc1, loc2) {
58693         var lat = (loc2[1] + loc1[1]) / 2,
58694             conversion = (isImperial ? 3.28084 : 1),
58695             dist = geoLonToMeters(loc2[0] - loc1[0], lat) * conversion,
58696             scale = { dist: 0, px: 0, text: '' },
58697             buckets, i, val, dLon;
58698
58699         if (isImperial) {
58700             buckets = [5280000, 528000, 52800, 5280, 500, 50, 5, 1];
58701         } else {
58702             buckets = [5000000, 500000, 50000, 5000, 500, 50, 5, 1];
58703         }
58704
58705         // determine a user-friendly endpoint for the scale
58706         for (i = 0; i < buckets.length; i++) {
58707             val = buckets[i];
58708             if (dist >= val) {
58709                 scale.dist = Math.floor(dist / val) * val;
58710                 break;
58711             } else {
58712                 scale.dist = +dist.toFixed(2);
58713             }
58714         }
58715
58716         dLon = geoMetersToLon(scale.dist / conversion, lat);
58717         scale.px = Math.round(projection([loc1[0] + dLon, loc1[1]])[0]);
58718
58719         if (isImperial) {
58720             if (scale.dist >= 5280) {
58721                 scale.dist /= 5280;
58722                 scale.text = String(scale.dist) + ' mi';
58723             } else {
58724                 scale.text = String(scale.dist) + ' ft';
58725             }
58726         } else {
58727             if (scale.dist >= 1000) {
58728                 scale.dist /= 1000;
58729                 scale.text = String(scale.dist) + ' km';
58730             } else {
58731                 scale.text = String(scale.dist) + ' m';
58732             }
58733         }
58734
58735         return scale;
58736     }
58737
58738
58739     function update(selection) {
58740         // choose loc1, loc2 along bottom of viewport (near where the scale will be drawn)
58741         var dims = context.map().dimensions(),
58742             loc1 = projection.invert([0, dims[1]]),
58743             loc2 = projection.invert([maxLength, dims[1]]),
58744             scale = scaleDefs(loc1, loc2);
58745
58746         selection.select('#scalepath')
58747             .attr('d', 'M0.5,0.5v' + tickHeight + 'h' + scale.px + 'v-' + tickHeight);
58748
58749         selection.select('#scaletext')
58750             .attr('x', scale.px + 8)
58751             .attr('y', tickHeight)
58752             .text(scale.text);
58753     }
58754
58755
58756     return function(selection) {
58757         function switchUnits() {
58758             isImperial = !isImperial;
58759             selection.call(update);
58760         }
58761
58762         var g = selection.append('svg')
58763             .attr('id', 'scale')
58764             .on('click', switchUnits)
58765             .append('g')
58766             .attr('transform', 'translate(10,11)');
58767
58768         g.append('path').attr('id', 'scalepath');
58769         g.append('text').attr('id', 'scaletext');
58770
58771         selection.call(update);
58772
58773         context.map().on('move.scale', function() {
58774             update(selection);
58775         });
58776     };
58777 }
58778
58779 var pair_1 = pair;
58780 function search(x, dims, r) {
58781   if (!dims) dims = 'NSEW';
58782   if (typeof x !== 'string') return { val: null, regex: r };
58783   r = r || /[\s\,]*([\-|\—|\―]?[0-9.]+)°? *(?:([0-9.]+)['’′‘] *)?(?:([0-9.]+)(?:''|"|”|″) *)?([NSEW])?/gi;
58784   var m = r.exec(x);
58785   if (!m) return { val: null, regex: r };
58786   else if (m[4] && dims.indexOf(m[4]) === -1) return { val: null, regex: r };
58787   else return {
58788     val: (((m[1]) ? parseFloat(m[1]) : 0) +
58789           ((m[2] ? parseFloat(m[2]) / 60 : 0)) +
58790           ((m[3] ? parseFloat(m[3]) / 3600 : 0))) *
58791           ((m[4] && m[4] === 'S' || m[4] === 'W') ? -1 : 1),
58792     regex: r,
58793     raw: m[0],
58794     dim: m[4]
58795   };
58796 }
58797
58798 function pair(x, dims) {
58799   x = x.trim();
58800   var one = search(x, dims);
58801   if (one.val === null) return null;
58802   var two = search(x, dims, one.regex);
58803   if (two.val === null) return null;
58804   // null if one/two are not contiguous.
58805   if (one.raw + two.raw !== x) return null;
58806   if (one.dim) {
58807     return swapdim(one.val, two.val, one.dim);
58808   } else {
58809     return [one.val, two.val];
58810   }
58811 }
58812
58813 function swapdim(a, b, dim) {
58814   if (dim === 'N' || dim === 'S') return [a, b];
58815   if (dim === 'W' || dim === 'E') return [b, a];
58816 }
58817
58818 function uiFeatureList(context) {
58819     var geocodeResults;
58820
58821
58822     function featureList(selection$$1) {
58823         var header = selection$$1.append('div')
58824             .attr('class', 'header fillL cf');
58825
58826         header.append('h3')
58827             .text(t('inspector.feature_list'));
58828
58829         var searchWrap = selection$$1.append('div')
58830             .attr('class', 'search-header');
58831
58832         var search = searchWrap.append('input')
58833             .attr('placeholder', t('inspector.search'))
58834             .attr('type', 'search')
58835             .on('keypress', keypress)
58836             .on('input', inputevent);
58837
58838         searchWrap
58839             .call(svgIcon('#icon-search', 'pre-text'));
58840
58841         var listWrap = selection$$1.append('div')
58842             .attr('class', 'inspector-body');
58843
58844         var list = listWrap.append('div')
58845             .attr('class', 'feature-list cf');
58846
58847         context
58848             .on('exit.feature-list', clearSearch);
58849         context.map()
58850             .on('drawn.feature-list', mapDrawn);
58851
58852
58853         function keypress() {
58854             var q = search.property('value'),
58855                 items = list.selectAll('.feature-list-item');
58856             if (event.keyCode === 13 && q.length && items.size()) {
58857                 click(items.datum());
58858             }
58859         }
58860
58861
58862         function inputevent() {
58863             geocodeResults = undefined;
58864             drawList();
58865         }
58866
58867
58868         function clearSearch() {
58869             search.property('value', '');
58870             drawList();
58871         }
58872
58873
58874         function mapDrawn(e) {
58875             if (e.full) {
58876                 drawList();
58877             }
58878         }
58879
58880
58881         function features() {
58882             var entities = {},
58883                 result = [],
58884                 graph = context.graph(),
58885                 q = search.property('value').toLowerCase();
58886
58887             if (!q) return result;
58888
58889             var idMatch = q.match(/^([nwr])([0-9]+)$/);
58890
58891             if (idMatch) {
58892                 result.push({
58893                     id: idMatch[0],
58894                     geometry: idMatch[1] === 'n' ? 'point' : idMatch[1] === 'w' ? 'line' : 'relation',
58895                     type: idMatch[1] === 'n' ? t('inspector.node') : idMatch[1] === 'w' ? t('inspector.way') : t('inspector.relation'),
58896                     name: idMatch[2]
58897                 });
58898             }
58899
58900             var locationMatch = pair_1(q.toUpperCase()) || q.match(/^(-?\d+\.?\d*)\s+(-?\d+\.?\d*)$/);
58901
58902             if (locationMatch) {
58903                 var loc = [parseFloat(locationMatch[0]), parseFloat(locationMatch[1])];
58904                 result.push({
58905                     id: -1,
58906                     geometry: 'point',
58907                     type: t('inspector.location'),
58908                     name: loc[0].toFixed(6) + ', ' + loc[1].toFixed(6),
58909                     location: loc
58910                 });
58911             }
58912
58913             function addEntity(entity) {
58914                 if (entity.id in entities || result.length > 200)
58915                     return;
58916
58917                 entities[entity.id] = true;
58918
58919                 var name = utilDisplayName(entity) || '';
58920                 if (name.toLowerCase().indexOf(q) >= 0) {
58921                     var matched = context.presets().match(entity, graph),
58922                         type = (matched && matched.name()) || utilDisplayType(entity.id);
58923                     result.push({
58924                         id: entity.id,
58925                         entity: entity,
58926                         geometry: context.geometry(entity.id),
58927                         type: type,
58928                         name: name
58929                     });
58930                 }
58931
58932                 graph.parentRelations(entity).forEach(function(parent) {
58933                     addEntity(parent);
58934                 });
58935             }
58936
58937             var visible = context.surface().selectAll('.point, .line, .area').nodes();
58938             for (var i = 0; i < visible.length && result.length <= 200; i++) {
58939                 addEntity(visible[i].__data__);
58940             }
58941
58942             (geocodeResults || []).forEach(function(d) {
58943                 // https://github.com/openstreetmap/iD/issues/1890
58944                 if (d.osm_type && d.osm_id) {
58945                     result.push({
58946                         id: osmEntity$$1.id.fromOSM(d.osm_type, d.osm_id),
58947                         geometry: d.osm_type === 'relation' ? 'relation' : d.osm_type === 'way' ? 'line' : 'point',
58948                         type: d.type !== 'yes' ? (d.type.charAt(0).toUpperCase() + d.type.slice(1)).replace('_', ' ')
58949                                                : (d.class.charAt(0).toUpperCase() + d.class.slice(1)).replace('_', ' '),
58950                         name: d.display_name,
58951                         extent: new geoExtent$$1(
58952                             [parseFloat(d.boundingbox[3]), parseFloat(d.boundingbox[0])],
58953                             [parseFloat(d.boundingbox[2]), parseFloat(d.boundingbox[1])])
58954                     });
58955                 }
58956             });
58957
58958             return result;
58959         }
58960
58961
58962         function drawList() {
58963             var value = search.property('value'),
58964                 results = features();
58965
58966             list.classed('filtered', value.length);
58967
58968             var noResultsWorldwide = geocodeResults && geocodeResults.length === 0;
58969
58970             var resultsIndicator = list.selectAll('.no-results-item')
58971                 .data([0])
58972                 .enter().append('button')
58973                 .property('disabled', true)
58974                 .attr('class', 'no-results-item')
58975                 .call(svgIcon('#icon-alert', 'pre-text'));
58976
58977             resultsIndicator.append('span')
58978                 .attr('class', 'entity-name');
58979
58980             list.selectAll('.no-results-item .entity-name')
58981                 .text(noResultsWorldwide ? t('geocoder.no_results_worldwide') : t('geocoder.no_results_visible'));
58982
58983             list.selectAll('.geocode-item')
58984                 .data([0])
58985                 .enter().append('button')
58986                 .attr('class', 'geocode-item')
58987                 .on('click', geocode)
58988                 .append('div')
58989                 .attr('class', 'label')
58990                 .append('span')
58991                 .attr('class', 'entity-name')
58992                 .text(t('geocoder.search'));
58993
58994             list.selectAll('.no-results-item')
58995                 .style('display', (value.length && !results.length) ? 'block' : 'none');
58996
58997             list.selectAll('.geocode-item')
58998                 .style('display', (value && geocodeResults === undefined) ? 'block' : 'none');
58999
59000             list.selectAll('.feature-list-item')
59001                 .data([-1])
59002                 .remove();
59003
59004             var items = list.selectAll('.feature-list-item')
59005                 .data(results, function(d) { return d.id; });
59006
59007             var enter = items.enter()
59008                 .insert('button', '.geocode-item')
59009                 .attr('class', 'feature-list-item')
59010                 .on('mouseover', mouseover)
59011                 .on('mouseout', mouseout)
59012                 .on('click', click);
59013
59014             var label = enter
59015                 .append('div')
59016                 .attr('class', 'label');
59017
59018             label.each(function(d) {
59019                 select(this)
59020                     .call(svgIcon('#icon-' + d.geometry, 'pre-text'));
59021             });
59022
59023             label.append('span')
59024                 .attr('class', 'entity-type')
59025                 .text(function(d) { return d.type; });
59026
59027             label.append('span')
59028                 .attr('class', 'entity-name')
59029                 .text(function(d) { return d.name; });
59030
59031             enter.style('opacity', 0)
59032                 .transition()
59033                 .style('opacity', 1);
59034
59035             items.order();
59036
59037             items.exit()
59038                 .remove();
59039         }
59040
59041
59042         function mouseover(d) {
59043             if (d.id === -1) return;
59044
59045             context.surface().selectAll(utilEntityOrMemberSelector([d.id], context.graph()))
59046                 .classed('hover', true);
59047         }
59048
59049
59050         function mouseout() {
59051             context.surface().selectAll('.hover')
59052                 .classed('hover', false);
59053         }
59054
59055
59056         function click(d) {
59057             event.preventDefault();
59058             if (d.location) {
59059                 context.map().centerZoom([d.location[1], d.location[0]], 20);
59060             }
59061             else if (d.entity) {
59062                 if (d.entity.type === 'node') {
59063                     context.map().center(d.entity.loc);
59064                 } else if (d.entity.type === 'way') {
59065                     var center = context.projection(context.map().center()),
59066                         edge = geoChooseEdge(context.childNodes(d.entity), center, context.projection);
59067                     context.map().center(edge.loc);
59068                 }
59069                 context.enter(modeSelect(context, [d.entity.id]).suppressMenu(true));
59070             } else {
59071                 context.zoomToEntity(d.id);
59072             }
59073         }
59074
59075
59076         function geocode() {
59077             var searchVal = encodeURIComponent(search.property('value'));
59078             json('https://nominatim.openstreetmap.org/search/' + searchVal + '?limit=10&format=json', function(err, resp) {
59079                 geocodeResults = resp || [];
59080                 drawList();
59081             });
59082         }
59083     }
59084
59085
59086     return featureList;
59087 }
59088
59089 function uiPresetIcon() {
59090     var preset, geometry;
59091
59092
59093     function presetIcon(selection$$1) {
59094         selection$$1.each(render);
59095     }
59096
59097
59098     function render() {
59099         var selection$$1 = select(this),
59100             p = preset.apply(this, arguments),
59101             geom = geometry.apply(this, arguments),
59102             picon = p.icon || (geom === 'line' ? 'other-line' : 'marker-stroked'),
59103             isMaki = dataFeatureIcons.hasOwnProperty(picon + '-24');
59104
59105         if (picon === 'dentist') {
59106             isMaki = true;  // workaround for dentist icon missing in `maki-sprite.json`
59107         }
59108
59109         function tag_classes(p) {
59110             var s = '';
59111             for (var i in p.tags) {
59112                 s += ' tag-' + i;
59113                 if (p.tags[i] !== '*') {
59114                     s += ' tag-' + i + '-' + p.tags[i];
59115                 }
59116             }
59117             return s;
59118         }
59119
59120         var fill = selection$$1.selectAll('.preset-icon-fill')
59121             .data([0]);
59122
59123         fill = fill.enter()
59124             .append('div')
59125             .merge(fill);
59126
59127         fill
59128             .attr('class', function() {
59129                 return 'preset-icon-fill preset-icon-fill-' + geom + tag_classes(p);
59130             });
59131
59132         var frame = selection$$1.selectAll('.preset-icon-frame')
59133             .data([0]);
59134
59135         frame = frame.enter()
59136             .append('div')
59137             .call(svgIcon('#preset-icon-frame'))
59138             .merge(frame);
59139
59140         frame
59141             .attr('class', function() {
59142                 return 'preset-icon-frame ' + (geom === 'area' ? '' : 'hide');
59143             });
59144
59145
59146         var icon = selection$$1.selectAll('.preset-icon')
59147             .data([0]);
59148
59149         icon = icon.enter()
59150             .append('div')
59151             .attr('class', 'preset-icon')
59152             .call(svgIcon(''))
59153             .merge(icon);
59154
59155         icon
59156             .attr('class', 'preset-icon preset-icon-' + (isMaki ? '32' : (geom === 'area' ? '44' : '60')));
59157
59158         icon.selectAll('svg')
59159             .attr('class', function() {
59160                 return 'icon ' + picon + tag_classes(p);
59161             });
59162
59163         icon.selectAll('use')       // workaround: maki parking-24 broken?
59164             .attr('href', '#' + picon + (isMaki ? (picon === 'parking' ? '-18' : '-24') : ''));
59165     }
59166
59167
59168     presetIcon.preset = function(_) {
59169         if (!arguments.length) return preset;
59170         preset = utilFunctor(_);
59171         return presetIcon;
59172     };
59173
59174
59175     presetIcon.geometry = function(_) {
59176         if (!arguments.length) return geometry;
59177         geometry = utilFunctor(_);
59178         return presetIcon;
59179     };
59180
59181     return presetIcon;
59182 }
59183
59184 function d3combobox() {
59185     var event$$1 = dispatch('accept'),
59186         data = [],
59187         suggestions = [],
59188         minItems = 2,
59189         caseSensitive = false;
59190
59191     var fetcher = function(val, cb) {
59192         cb(data.filter(function(d) {
59193             return d.value
59194                 .toString()
59195                 .toLowerCase()
59196                 .indexOf(val.toLowerCase()) !== -1;
59197         }));
59198     };
59199
59200     var combobox = function(input, attachTo) {
59201         var idx = -1,
59202             container = select(document.body)
59203                 .selectAll('div.combobox')
59204                 .filter(function(d) { return d === input.node(); }),
59205             shown = !container.empty();
59206
59207         input
59208             .classed('combobox-input', true)
59209             .on('focus.typeahead', focus)
59210             .on('blur.typeahead', blur)
59211             .on('keydown.typeahead', keydown)
59212             .on('keyup.typeahead', keyup)
59213             .on('input.typeahead', change)
59214             .each(function() {
59215                 var parent = this.parentNode,
59216                     sibling = this.nextSibling;
59217
59218                 var caret = select(parent).selectAll('.combobox-caret')
59219                     .filter(function(d) { return d === input.node(); })
59220                     .data([input.node()]);
59221
59222                 caret = caret.enter()
59223                   .insert('div', function() { return sibling; })
59224                     .attr('class', 'combobox-caret')
59225                   .merge(caret);
59226
59227                 caret
59228                     .on('mousedown', function () {
59229                         // prevent the form element from blurring. it blurs
59230                         // on mousedown
59231                         event.stopPropagation();
59232                         event.preventDefault();
59233                         if (!shown) {
59234                             input.node().focus();
59235                             fetch('', render);
59236                         } else {
59237                             hide();
59238                         }
59239                     });
59240             });
59241
59242         function focus() {
59243             fetch(value(), render);
59244         }
59245
59246         function blur() {
59247             window.setTimeout(hide, 150);
59248         }
59249
59250         function show() {
59251             if (!shown) {
59252                 container = select(document.body)
59253                     .insert('div', ':first-child')
59254                     .datum(input.node())
59255                     .attr('class', 'combobox')
59256                     .style('position', 'absolute')
59257                     .style('display', 'block')
59258                     .style('left', '0px')
59259                     .on('mousedown', function () {
59260                         // prevent moving focus out of the text field
59261                         event.preventDefault();
59262                     });
59263
59264                 select(document.body)
59265                     .on('scroll.combobox', render, true);
59266
59267                 shown = true;
59268             }
59269         }
59270
59271         function hide() {
59272             if (shown) {
59273                 idx = -1;
59274                 container.remove();
59275
59276                 select(document.body)
59277                     .on('scroll.combobox', null);
59278
59279                 shown = false;
59280             }
59281         }
59282
59283         function keydown() {
59284            switch (event.keyCode) {
59285                // backspace, delete
59286                case 8:
59287                case 46:
59288                    input.on('input.typeahead', function() {
59289                        idx = -1;
59290                        render();
59291                        var start = input.property('selectionStart');
59292                        input.node().setSelectionRange(start, start);
59293                        input.on('input.typeahead', change);
59294                    });
59295                    break;
59296                // tab
59297                case 9:
59298                    container.selectAll('a.selected').each(function (d) {
59299                        event$$1.call('accept', this, d);
59300                    });
59301                    hide();
59302                    break;
59303                // return
59304                case 13:
59305                    event.preventDefault();
59306                    break;
59307                // up arrow
59308                case 38:
59309                    nav(-1);
59310                    event.preventDefault();
59311                    break;
59312                // down arrow
59313                case 40:
59314                    nav(+1);
59315                    event.preventDefault();
59316                    break;
59317            }
59318            event.stopPropagation();
59319         }
59320
59321         function keyup() {
59322             switch (event.keyCode) {
59323                 // escape
59324                 case 27:
59325                     hide();
59326                     break;
59327                 // return
59328                 case 13:
59329                     container.selectAll('a.selected').each(function (d) {
59330                        event$$1.call('accept', this, d);
59331                     });
59332                     hide();
59333                     break;
59334             }
59335         }
59336
59337         function change() {
59338             fetch(value(), function() {
59339                 if (input.property('selectionEnd') === input.property('value').length) {
59340                     autocomplete();
59341                 }
59342                 render();
59343             });
59344         }
59345
59346         function nav(dir) {
59347             if (!suggestions.length) return;
59348             idx = Math.max(Math.min(idx + dir, suggestions.length - 1), 0);
59349             input.property('value', suggestions[idx].value);
59350             render();
59351             ensureVisible();
59352         }
59353
59354         function value() {
59355             var value = input.property('value'),
59356                 start = input.property('selectionStart'),
59357                 end = input.property('selectionEnd');
59358
59359             if (start && end) {
59360                 value = value.substring(0, start);
59361             }
59362
59363             return value;
59364         }
59365
59366         function fetch(v, cb) {
59367             fetcher.call(input, v, function(_) {
59368                 suggestions = _;
59369                 cb();
59370             });
59371         }
59372
59373         function autocomplete() {
59374             var v = caseSensitive ? value() : value().toLowerCase();
59375             idx = -1;
59376             if (!v) return;
59377
59378             for (var i = 0; i < suggestions.length; i++) {
59379                 var suggestion = suggestions[i].value,
59380                     compare = caseSensitive ? suggestion : suggestion.toLowerCase();
59381
59382                 if (compare.indexOf(v) === 0) {
59383                     idx = i;
59384                     input.property('value', suggestion);
59385                     input.node().setSelectionRange(v.length, suggestion.length);
59386                     return;
59387                 }
59388             }
59389         }
59390
59391         function render() {
59392             if (suggestions.length >= minItems && document.activeElement === input.node()) {
59393                 show();
59394             } else {
59395                 hide();
59396                 return;
59397             }
59398
59399             var options = container
59400                 .selectAll('a.combobox-option')
59401                 .data(suggestions, function(d) { return d.value; });
59402
59403             options.exit()
59404                 .remove();
59405
59406             options.enter()
59407                 .append('a')
59408                 .attr('class', 'combobox-option')
59409                 .text(function(d) { return d.value; })
59410                 .merge(options)
59411                 .attr('title', function(d) { return d.title; })
59412                 .classed('selected', function(d, i) { return i === idx; })
59413                 .on('mouseover', select$$1)
59414                 .on('click', accept)
59415                 .order();
59416
59417
59418             var node = attachTo ? attachTo.node() : input.node(),
59419                 rect = node.getBoundingClientRect();
59420
59421             container
59422                 .style('left', rect.left + 'px')
59423                 .style('width', rect.width + 'px')
59424                 .style('top', rect.height + rect.top + 'px');
59425         }
59426
59427         function select$$1(d, i) {
59428             idx = i;
59429             render();
59430         }
59431
59432         function ensureVisible() {
59433             var node = container.selectAll('a.selected').node();
59434             if (node) node.scrollIntoView();
59435         }
59436
59437         function accept(d) {
59438             if (!shown) return;
59439             input
59440                 .property('value', d.value)
59441                 .dispatch('change');
59442             event$$1.call('accept', this, d);
59443             hide();
59444         }
59445     };
59446
59447     combobox.fetcher = function(_) {
59448         if (!arguments.length) return fetcher;
59449         fetcher = _;
59450         return combobox;
59451     };
59452
59453     combobox.data = function(_) {
59454         if (!arguments.length) return data;
59455         data = _;
59456         return combobox;
59457     };
59458
59459     combobox.minItems = function(_) {
59460         if (!arguments.length) return minItems;
59461         minItems = _;
59462         return combobox;
59463     };
59464
59465     combobox.caseSensitive = function(_) {
59466         if (!arguments.length) return caseSensitive;
59467         caseSensitive = _;
59468         return combobox;
59469     };
59470
59471     return utilRebind(combobox, event$$1, 'on');
59472 }
59473
59474
59475 d3combobox.off = function(input) {
59476     input
59477         .on('focus.typeahead', null)
59478         .on('blur.typeahead', null)
59479         .on('keydown.typeahead', null)
59480         .on('keyup.typeahead', null)
59481         .on('input.typeahead', null)
59482         .each(function() {
59483             select(this.parentNode).selectAll('.combobox-caret')
59484                 .filter(function(d) { return d === input.node(); })
59485                 .on('mousedown', null);
59486         });
59487
59488     select(document.body)
59489         .on('scroll.combobox', null);
59490 };
59491
59492 function uiDisclosure() {
59493     var dispatch$$1 = dispatch('toggled'),
59494         title,
59495         expanded = false,
59496         content = function () {};
59497
59498
59499     var disclosure = function(selection$$1) {
59500         var hideToggle = selection$$1.selectAll('.hide-toggle')
59501             .data([0]);
59502
59503         hideToggle = hideToggle.enter()
59504             .append('a')
59505             .attr('href', '#')
59506             .attr('class', 'hide-toggle')
59507             .merge(hideToggle);
59508
59509         hideToggle
59510             .text(title)
59511             .on('click', toggle)
59512             .classed('expanded', expanded);
59513
59514
59515         var wrap = selection$$1.selectAll('div')
59516             .data([0]);
59517
59518         wrap = wrap.enter()
59519             .append('div')
59520             .merge(wrap);
59521
59522         wrap
59523             .classed('hide', !expanded)
59524             .call(content);
59525
59526
59527         function toggle() {
59528             expanded = !expanded;
59529             hideToggle.classed('expanded', expanded);
59530             wrap.call(uiToggle(expanded));
59531             dispatch$$1.call('toggled', this, expanded);
59532         }
59533     };
59534
59535
59536     disclosure.title = function(_) {
59537         if (!arguments.length) return title;
59538         title = _;
59539         return disclosure;
59540     };
59541
59542
59543     disclosure.expanded = function(_) {
59544         if (!arguments.length) return expanded;
59545         expanded = _;
59546         return disclosure;
59547     };
59548
59549
59550     disclosure.content = function(_) {
59551         if (!arguments.length) return content;
59552         content = _;
59553         return disclosure;
59554     };
59555
59556
59557     return utilRebind(disclosure, dispatch$$1, 'on');
59558 }
59559
59560 function uiRawMemberEditor(context) {
59561     var id,
59562         taginfo = services.taginfo;
59563
59564
59565     function selectMember(d) {
59566         event.preventDefault();
59567         context.enter(modeSelect(context, [d.id]));
59568     }
59569
59570
59571     function changeRole(d) {
59572         var role = select(this).property('value');
59573         var member = { id: d.id, type: d.type, role: role };
59574         context.perform(
59575             actionChangeMember(d.relation.id, member, d.index),
59576             t('operations.change_role.annotation')
59577         );
59578     }
59579
59580
59581     function deleteMember(d) {
59582         context.perform(
59583             actionDeleteMember(d.relation.id, d.index),
59584             t('operations.delete_member.annotation')
59585         );
59586
59587         if (!context.hasEntity(d.relation.id)) {
59588             context.enter(modeBrowse$$1(context));
59589         }
59590     }
59591
59592
59593     function rawMemberEditor(selection$$1) {
59594         var entity = context.entity(id),
59595             memberships = [];
59596
59597         entity.members.forEach(function(member, index) {
59598             memberships.push({
59599                 index: index,
59600                 id: member.id,
59601                 type: member.type,
59602                 role: member.role,
59603                 relation: entity,
59604                 member: context.hasEntity(member.id)
59605             });
59606         });
59607
59608         selection$$1.call(uiDisclosure()
59609             .title(t('inspector.all_members') + ' (' + memberships.length + ')')
59610             .expanded(true)
59611             .on('toggled', toggled)
59612             .content(content)
59613         );
59614
59615
59616         function toggled(expanded) {
59617             if (expanded) {
59618                 selection$$1.node().parentNode.scrollTop += 200;
59619             }
59620         }
59621
59622
59623         function content(wrap) {
59624             var list = wrap.selectAll('.member-list')
59625                 .data([0]);
59626
59627             list = list.enter()
59628                 .append('ul')
59629                 .attr('class', 'member-list')
59630                 .merge(list);
59631
59632
59633             var items = list.selectAll('li')
59634                 .data(memberships, function(d) {
59635                     return osmEntity$$1.key(d.relation) + ',' + d.index + ',' +
59636                         (d.member ? osmEntity$$1.key(d.member) : 'incomplete');
59637                 });
59638
59639             items.exit()
59640                 .each(unbind)
59641                 .remove();
59642
59643             var enter = items.enter()
59644                 .append('li')
59645                 .attr('class', 'member-row form-field')
59646                 .classed('member-incomplete', function(d) { return !d.member; });
59647
59648             enter
59649                 .each(function(d) {
59650                     if (d.member) {
59651                         var label = select(this).append('label')
59652                             .attr('class', 'form-label')
59653                             .append('a')
59654                             .attr('href', '#')
59655                             .on('click', selectMember);
59656
59657                         label.append('span')
59658                             .attr('class', 'member-entity-type')
59659                             .text(function(d) {
59660                                 var matched = context.presets().match(d.member, context.graph());
59661                                 return (matched && matched.name()) || utilDisplayType(d.member.id);
59662                             });
59663
59664                         label.append('span')
59665                             .attr('class', 'member-entity-name')
59666                             .text(function(d) { return utilDisplayName(d.member); });
59667
59668                     } else {
59669                         select(this).append('label')
59670                             .attr('class', 'form-label')
59671                             .text(t('inspector.incomplete', { id: d.id }));
59672                     }
59673                 });
59674
59675             enter
59676                 .append('input')
59677                 .attr('class', 'member-role')
59678                 .property('type', 'text')
59679                 .attr('maxlength', 255)
59680                 .attr('placeholder', t('inspector.role'))
59681                 .property('value', function(d) { return d.role; })
59682                 .on('change', changeRole);
59683
59684             enter
59685                 .append('button')
59686                 .attr('tabindex', -1)
59687                 .attr('class', 'remove button-input-action member-delete minor')
59688                 .on('click', deleteMember)
59689                 .call(svgIcon('#operation-delete'));
59690
59691             if (taginfo) {
59692                 enter.each(bindTypeahead);
59693             }
59694
59695
59696             function bindTypeahead(d) {
59697                 var row = select(this),
59698                     role = row.selectAll('input.member-role');
59699
59700                 function sort(value, data) {
59701                     var sameletter = [],
59702                         other = [];
59703                     for (var i = 0; i < data.length; i++) {
59704                         if (data[i].value.substring(0, value.length) === value) {
59705                             sameletter.push(data[i]);
59706                         } else {
59707                             other.push(data[i]);
59708                         }
59709                     }
59710                     return sameletter.concat(other);
59711                 }
59712
59713                 role.call(d3combobox()
59714                     .fetcher(function(role, callback) {
59715                         var rtype = entity.tags.type;
59716                         taginfo.roles({
59717                             debounce: true,
59718                             rtype: rtype || '',
59719                             geometry: context.geometry(d.member.id),
59720                             query: role
59721                         }, function(err, data) {
59722                             if (!err) callback(sort(role, data));
59723                         });
59724                     }));
59725             }
59726
59727
59728             function unbind() {
59729                 var row = select(this);
59730
59731                 row.selectAll('input.member-role')
59732                     .call(d3combobox.off);
59733             }
59734         }
59735     }
59736
59737
59738     rawMemberEditor.entityID = function(_) {
59739         if (!arguments.length) return id;
59740         id = _;
59741         return rawMemberEditor;
59742     };
59743
59744
59745     return rawMemberEditor;
59746 }
59747
59748 function uiRawMembershipEditor(context) {
59749     var taginfo = services.taginfo,
59750         id, showBlank;
59751
59752
59753     function selectRelation(d) {
59754         event.preventDefault();
59755         context.enter(modeSelect(context, [d.relation.id]));
59756     }
59757
59758
59759     function changeRole(d) {
59760         var role = select(this).property('value');
59761         context.perform(
59762             actionChangeMember(d.relation.id, lodash.extend({}, d.member, { role: role }), d.index),
59763             t('operations.change_role.annotation')
59764         );
59765     }
59766
59767
59768     function addMembership(d, role) {
59769         showBlank = false;
59770
59771         if (d.relation) {
59772             context.perform(
59773                 actionAddMember(d.relation.id, { id: id, type: context.entity(id).type, role: role }),
59774                 t('operations.add_member.annotation')
59775             );
59776
59777         } else {
59778             var relation = osmRelation();
59779             context.perform(
59780                 actionAddEntity(relation),
59781                 actionAddMember(relation.id, { id: id, type: context.entity(id).type, role: role }),
59782                 t('operations.add.annotation.relation')
59783             );
59784
59785             context.enter(modeSelect(context, [relation.id]));
59786         }
59787     }
59788
59789
59790     function deleteMembership(d) {
59791         context.perform(
59792             actionDeleteMember(d.relation.id, d.index),
59793             t('operations.delete_member.annotation')
59794         );
59795     }
59796
59797
59798     function relations(q) {
59799         var newRelation = {
59800                 relation: null,
59801                 value: t('inspector.new_relation')
59802             },
59803             result = [],
59804             graph = context.graph();
59805
59806         context.intersects(context.extent()).forEach(function(entity) {
59807             if (entity.type !== 'relation' || entity.id === id)
59808                 return;
59809
59810             var matched = context.presets().match(entity, graph),
59811                 presetName = (matched && matched.name()) || t('inspector.relation'),
59812                 entityName = utilDisplayName(entity) || '';
59813
59814             var value = presetName + ' ' + entityName;
59815             if (q && value.toLowerCase().indexOf(q.toLowerCase()) === -1)
59816                 return;
59817
59818             result.push({
59819                 relation: entity,
59820                 value: value
59821             });
59822         });
59823
59824         result.sort(function(a, b) {
59825             return osmRelation.creationOrder(a.relation, b.relation);
59826         });
59827
59828         // Dedupe identical names by appending relation id - see #2891
59829         var dupeGroups = lodash(result)
59830             .groupBy('value')
59831             .filter(function(v) { return v.length > 1; })
59832             .value();
59833
59834         dupeGroups.forEach(function(group) {
59835             group.forEach(function(obj) {
59836                 obj.value += ' ' + obj.relation.id;
59837             });
59838         });
59839
59840         result.unshift(newRelation);
59841         return result;
59842     }
59843
59844
59845     function rawMembershipEditor(selection$$1) {
59846         var entity = context.entity(id),
59847             memberships = [];
59848
59849         context.graph().parentRelations(entity).forEach(function(relation) {
59850             relation.members.forEach(function(member, index) {
59851                 if (member.id === entity.id) {
59852                     memberships.push({ relation: relation, member: member, index: index });
59853                 }
59854             });
59855         });
59856
59857         selection$$1.call(uiDisclosure()
59858             .title(t('inspector.all_relations') + ' (' + memberships.length + ')')
59859             .expanded(true)
59860             .on('toggled', toggled)
59861             .content(content)
59862         );
59863
59864
59865         function toggled(expanded) {
59866             if (expanded) {
59867                 selection$$1.node().parentNode.scrollTop += 200;
59868             }
59869         }
59870
59871
59872         function content(wrap) {
59873             var list = wrap.selectAll('.member-list')
59874                 .data([0]);
59875
59876             list = list.enter()
59877                 .append('ul')
59878                 .attr('class', 'member-list')
59879                 .merge(list);
59880
59881
59882             var items = list.selectAll('li.member-row-normal')
59883                 .data(memberships, function(d) {
59884                     return osmEntity$$1.key(d.relation) + ',' + d.index;
59885                 });
59886
59887             items.exit()
59888                 .each(unbind)
59889                 .remove();
59890
59891             var enter = items.enter()
59892                 .append('li')
59893                 .attr('class', 'member-row member-row-normal form-field');
59894
59895             var label = enter
59896                 .append('label')
59897                 .attr('class', 'form-label')
59898                 .append('a')
59899                 .attr('href', '#')
59900                 .on('click', selectRelation);
59901
59902             label
59903                 .append('span')
59904                 .attr('class', 'member-entity-type')
59905                 .text(function(d) {
59906                     var matched = context.presets().match(d.relation, context.graph());
59907                     return (matched && matched.name()) || t('inspector.relation');
59908                 });
59909
59910             label
59911                 .append('span')
59912                 .attr('class', 'member-entity-name')
59913                 .text(function(d) { return utilDisplayName(d.relation); });
59914
59915             enter
59916                 .append('input')
59917                 .attr('class', 'member-role')
59918                 .property('type', 'text')
59919                 .attr('maxlength', 255)
59920                 .attr('placeholder', t('inspector.role'))
59921                 .property('value', function(d) { return d.member.role; })
59922                 .on('change', changeRole);
59923
59924             enter
59925                 .append('button')
59926                 .attr('tabindex', -1)
59927                 .attr('class', 'remove button-input-action member-delete minor')
59928                 .on('click', deleteMembership)
59929                 .call(svgIcon('#operation-delete'));
59930
59931             if (taginfo) {
59932                 enter.each(bindTypeahead);
59933             }
59934
59935
59936             var newrow = list.selectAll('.member-row-new')
59937                 .data(showBlank ? [0] : []);
59938
59939             newrow.exit()
59940                 .remove();
59941
59942             enter = newrow.enter()
59943                 .append('li')
59944                 .attr('class', 'member-row member-row-new form-field');
59945
59946             enter
59947                 .append('input')
59948                 .attr('type', 'text')
59949                 .attr('class', 'member-entity-input');
59950
59951             enter
59952                 .append('input')
59953                 .attr('class', 'member-role')
59954                 .property('type', 'text')
59955                 .attr('maxlength', 255)
59956                 .attr('placeholder', t('inspector.role'))
59957                 .on('change', changeRole);
59958
59959             enter
59960                 .append('button')
59961                 .attr('tabindex', -1)
59962                 .attr('class', 'remove button-input-action member-delete minor')
59963                 .on('click', deleteMembership)
59964                 .call(svgIcon('#operation-delete'));
59965
59966             newrow = newrow
59967                 .merge(enter);
59968
59969             newrow.selectAll('.member-entity-input')
59970                 .call(d3combobox()
59971                     .minItems(1)
59972                     .fetcher(function(value, callback) { callback(relations(value)); })
59973                     .on('accept', onAccept)
59974                 );
59975
59976
59977             var addrel = wrap.selectAll('.add-relation')
59978                 .data([0]);
59979
59980             addrel = addrel.enter()
59981                 .append('button')
59982                 .attr('class', 'add-relation')
59983                 .merge(addrel);
59984
59985             addrel
59986                 .call(svgIcon('#icon-plus', 'light'))
59987                 .on('click', function() {
59988                     showBlank = true;
59989                     content(wrap);
59990                     list.selectAll('.member-entity-input').node().focus();
59991                 });
59992
59993
59994             function onAccept(d) {
59995                 var role = list.selectAll('.member-row-new .member-role').property('value');
59996                 addMembership(d, role);
59997             }
59998
59999
60000             function bindTypeahead(d) {
60001                 var row = select(this),
60002                     role = row.selectAll('input.member-role');
60003
60004                 function sort(value, data) {
60005                     var sameletter = [],
60006                         other = [];
60007                     for (var i = 0; i < data.length; i++) {
60008                         if (data[i].value.substring(0, value.length) === value) {
60009                             sameletter.push(data[i]);
60010                         } else {
60011                             other.push(data[i]);
60012                         }
60013                     }
60014                     return sameletter.concat(other);
60015                 }
60016
60017                 role.call(d3combobox()
60018                     .fetcher(function(role, callback) {
60019                         var rtype = d.relation.tags.type;
60020                         taginfo.roles({
60021                             debounce: true,
60022                             rtype: rtype || '',
60023                             geometry: context.geometry(id),
60024                             query: role
60025                         }, function(err, data) {
60026                             if (!err) callback(sort(role, data));
60027                         });
60028                     }));
60029             }
60030
60031
60032             function unbind() {
60033                 var row = select(this);
60034
60035                 row.selectAll('input.member-role')
60036                     .call(d3combobox.off);
60037             }
60038         }
60039     }
60040
60041
60042     rawMembershipEditor.entityID = function(_) {
60043         if (!arguments.length) return id;
60044         id = _;
60045         return rawMembershipEditor;
60046     };
60047
60048
60049     return rawMembershipEditor;
60050 }
60051
60052 function uiTagReference(tag) {
60053     var taginfo = services.taginfo,
60054         tagReference = {},
60055         button,
60056         body,
60057         loaded,
60058         showing;
60059
60060
60061     function findLocal(data) {
60062         var locale = utilDetect().locale.toLowerCase(),
60063             localized;
60064
60065         localized = lodash.find(data, function(d) {
60066             return d.lang.toLowerCase() === locale;
60067         });
60068         if (localized) return localized;
60069
60070         // try the non-regional version of a language, like
60071         // 'en' if the language is 'en-US'
60072         if (locale.indexOf('-') !== -1) {
60073             var first = locale.split('-')[0];
60074             localized = lodash.find(data, function(d) {
60075                 return d.lang.toLowerCase() === first;
60076             });
60077             if (localized) return localized;
60078         }
60079
60080         // finally fall back to english
60081         return lodash.find(data, function(d) {
60082             return d.lang.toLowerCase() === 'en';
60083         });
60084     }
60085
60086
60087     function load(param) {
60088         if (!taginfo) return;
60089
60090         button.classed('tag-reference-loading', true);
60091
60092         taginfo.docs(param, function show(err, data) {
60093             var docs;
60094             if (!err && data) {
60095                 docs = findLocal(data);
60096             }
60097
60098             body.html('');
60099
60100
60101             if (!docs || !docs.title) {
60102                 if (param.hasOwnProperty('value')) {
60103                     load(lodash.omit(param, 'value'));   // retry with key only
60104                 } else {
60105                     body.append('p').text(t('inspector.no_documentation_key'));
60106                     done();
60107                 }
60108                 return;
60109             }
60110
60111
60112             if (docs.image && docs.image.thumb_url_prefix) {
60113                 body
60114                     .append('img')
60115                     .attr('class', 'wiki-image')
60116                     .attr('src', docs.image.thumb_url_prefix + '100' + docs.image.thumb_url_suffix)
60117                     .on('load', function() { done(); })
60118                     .on('error', function() { select(this).remove(); done(); });
60119             } else {
60120                 done();
60121             }
60122
60123             body
60124                 .append('p')
60125                 .text(docs.description || t('inspector.documentation_redirect'));
60126
60127             body
60128                 .append('a')
60129                 .attr('target', '_blank')
60130                 .attr('tabindex', -1)
60131                 .attr('href', 'https://wiki.openstreetmap.org/wiki/' + docs.title)
60132                 .call(svgIcon('#icon-out-link', 'inline'))
60133                 .append('span')
60134                 .text(t('inspector.reference'));
60135         });
60136     }
60137
60138
60139     function done() {
60140         loaded = true;
60141
60142         button.classed('tag-reference-loading', false);
60143
60144         body.transition()
60145             .duration(200)
60146             .style('max-height', '200px')
60147             .style('opacity', '1');
60148
60149         showing = true;
60150     }
60151
60152
60153     function hide(selection$$1) {
60154         selection$$1 = selection$$1 || body.transition().duration(200);
60155
60156         selection$$1
60157             .style('max-height', '0px')
60158             .style('opacity', '0');
60159
60160         showing = false;
60161     }
60162
60163
60164     tagReference.button = function(selection$$1) {
60165         button = selection$$1.selectAll('.tag-reference-button')
60166             .data([0]);
60167
60168         button = button.enter()
60169             .append('button')
60170             .attr('class', 'tag-reference-button')
60171             .attr('tabindex', -1)
60172             .call(svgIcon('#icon-inspect'))
60173             .merge(button);
60174
60175         button
60176             .on('click', function () {
60177                 event.stopPropagation();
60178                 event.preventDefault();
60179                 if (showing) {
60180                     hide();
60181                 } else if (loaded) {
60182                     done();
60183                 } else {
60184                     load(tag);
60185                 }
60186             });
60187     };
60188
60189
60190     tagReference.body = function(selection$$1) {
60191         body = selection$$1.selectAll('.tag-reference-body')
60192             .data([0]);
60193
60194         body = body.enter()
60195             .append('div')
60196             .attr('class', 'tag-reference-body cf')
60197             .style('max-height', '0')
60198             .style('opacity', '0')
60199             .merge(body);
60200
60201         if (showing === false) {
60202             hide(body);
60203         }
60204     };
60205
60206
60207     tagReference.showing = function(_) {
60208         if (!arguments.length) return showing;
60209         showing = _;
60210         return tagReference;
60211     };
60212
60213
60214     return tagReference;
60215 }
60216
60217 function uiRawTagEditor(context) {
60218     var taginfo = services.taginfo,
60219         dispatch$$1 = dispatch('change'),
60220         showBlank = false,
60221         state,
60222         preset,
60223         tags,
60224         id;
60225
60226
60227     function rawTagEditor(selection$$1) {
60228         var count = Object.keys(tags).filter(function(d) { return d; }).length;
60229
60230         selection$$1.call(uiDisclosure()
60231             .title(t('inspector.all_tags') + ' (' + count + ')')
60232             .expanded(context.storage('raw_tag_editor.expanded') === 'true' || preset.isFallback())
60233             .on('toggled', toggled)
60234             .content(content));
60235
60236         function toggled(expanded) {
60237             context.storage('raw_tag_editor.expanded', expanded);
60238             if (expanded) {
60239                 selection$$1.node().parentNode.scrollTop += 200;
60240             }
60241         }
60242     }
60243
60244
60245     function content(wrap) {
60246         var entries$$1 = entries(tags);
60247
60248         if (!entries$$1.length || showBlank) {
60249             showBlank = false;
60250             entries$$1.push({key: '', value: ''});
60251         }
60252
60253         var list = wrap.selectAll('.tag-list')
60254             .data([0]);
60255
60256         list = list.enter()
60257             .append('ul')
60258             .attr('class', 'tag-list')
60259             .merge(list);
60260
60261         var newTag = wrap.selectAll('.add-tag')
60262             .data([0]);
60263
60264         newTag.enter()
60265             .append('button')
60266             .attr('class', 'add-tag')
60267             .on('click', addTag)
60268             .call(svgIcon('#icon-plus', 'light'));
60269
60270
60271         var items = list.selectAll('.tag-row')
60272             .data(entries$$1, function(d) { return d.key; });
60273
60274         items.exit()
60275             .each(unbind)
60276             .remove();
60277
60278         // Enter
60279
60280         var enter = items.enter()
60281             .append('li')
60282             .attr('class', 'tag-row cf');
60283
60284         enter
60285             .append('div')
60286             .attr('class', 'key-wrap')
60287             .append('input')
60288             .property('type', 'text')
60289             .attr('class', 'key')
60290             .attr('maxlength', 255)
60291             .on('blur', keyChange)
60292             .on('change', keyChange);
60293
60294         enter
60295             .append('div')
60296             .attr('class', 'input-wrap-position')
60297             .append('input')
60298             .property('type', 'text')
60299             .attr('class', 'value')
60300             .attr('maxlength', 255)
60301             .on('blur', valueChange)
60302             .on('change', valueChange)
60303             .on('keydown.push-more', pushMore);
60304
60305         enter
60306             .append('button')
60307             .attr('tabindex', -1)
60308             .attr('class', 'remove minor')
60309             .call(svgIcon('#operation-delete'));
60310
60311
60312         // Update
60313
60314         items = items
60315             .merge(enter)
60316             .sort(function(a, b) {
60317                 return (a.key === '') ? 1
60318                     : (b.key === '') ? -1
60319                     : ascending(a.key, b.key);
60320             });
60321
60322         items
60323             .each(function(tag) {
60324                 var row = select(this),
60325                     key = row.select('input.key'),      // propagate bound data to child
60326                     value = row.select('input.value');  // propagate bound data to child
60327
60328                 if (taginfo) {
60329                     bindTypeahead(key, value);
60330                 }
60331
60332                 var isRelation = (context.entity(id).type === 'relation'),
60333                     reference;
60334
60335                 if (isRelation && tag.key === 'type') {
60336                     reference = uiTagReference({ rtype: tag.value }, context);
60337                 } else {
60338                     reference = uiTagReference({ key: tag.key, value: tag.value }, context);
60339                 }
60340
60341                 if (state === 'hover') {
60342                     reference.showing(false);
60343                 }
60344
60345                 row
60346                     .call(reference.button)
60347                     .call(reference.body);
60348             });
60349
60350         items.selectAll('input.key')
60351             .attr('title', function(d) { return d.key; })
60352             .call(utilGetSetValue, function(d) { return d.key; });
60353
60354         items.selectAll('input.value')
60355             .attr('title', function(d) { return d.value; })
60356             .call(utilGetSetValue, function(d) { return d.value; });
60357
60358         items.selectAll('button.remove')
60359             .on('click', removeTag);
60360
60361
60362         function pushMore() {
60363             if (event.keyCode === 9 && !event.shiftKey &&
60364                 list.selectAll('li:last-child input.value').node() === this) {
60365                 addTag();
60366             }
60367         }
60368
60369
60370         function bindTypeahead(key, value) {
60371
60372             function sort(value, data) {
60373                 var sameletter = [],
60374                     other = [];
60375                 for (var i = 0; i < data.length; i++) {
60376                     if (data[i].value.substring(0, value.length) === value) {
60377                         sameletter.push(data[i]);
60378                     } else {
60379                         other.push(data[i]);
60380                     }
60381                 }
60382                 return sameletter.concat(other);
60383             }
60384
60385             key.call(d3combobox()
60386                 .fetcher(function(value, callback) {
60387                     taginfo.keys({
60388                         debounce: true,
60389                         geometry: context.geometry(id),
60390                         query: value
60391                     }, function(err, data) {
60392                         if (!err) callback(sort(value, data));
60393                     });
60394                 }));
60395
60396             value.call(d3combobox()
60397                 .fetcher(function(value, callback) {
60398                     taginfo.values({
60399                         debounce: true,
60400                         key: utilGetSetValue(key),
60401                         geometry: context.geometry(id),
60402                         query: value
60403                     }, function(err, data) {
60404                         if (!err) callback(sort(value, data));
60405                     });
60406                 }));
60407         }
60408
60409
60410         function unbind() {
60411             var row = select(this);
60412
60413             row.selectAll('input.key')
60414                 .call(d3combobox.off);
60415
60416             row.selectAll('input.value')
60417                 .call(d3combobox.off);
60418         }
60419
60420
60421         function keyChange(d) {
60422             var kOld = d.key,
60423                 kNew = this.value.trim(),
60424                 tag = {};
60425
60426             if (kNew && kNew !== kOld) {
60427                 var match = kNew.match(/^(.*?)(?:_(\d+))?$/),
60428                     base = match[1],
60429                     suffix = +(match[2] || 1);
60430                 while (tags[kNew]) {  // rename key if already in use
60431                     kNew = base + '_' + suffix++;
60432                 }
60433             }
60434             tag[kOld] = undefined;
60435             tag[kNew] = d.value;
60436             d.key = kNew; // Maintain DOM identity through the subsequent update.
60437             this.value = kNew;
60438             dispatch$$1.call('change', this, tag);
60439         }
60440
60441
60442         function valueChange(d) {
60443             var tag = {};
60444             tag[d.key] = this.value;
60445             dispatch$$1.call('change', this, tag);
60446         }
60447
60448
60449         function removeTag(d) {
60450             var tag = {};
60451             tag[d.key] = undefined;
60452             dispatch$$1.call('change', this, tag);
60453             select(this.parentNode).remove();
60454         }
60455
60456
60457         function addTag() {
60458             // Wrapped in a setTimeout in case it's being called from a blur
60459             // handler. Without the setTimeout, the call to `content` would
60460             // wipe out the pending value change.
60461             setTimeout(function() {
60462                 showBlank = true;
60463                 content(wrap);
60464                 list.selectAll('li:last-child input.key').node().focus();
60465             }, 0);
60466         }
60467     }
60468
60469
60470     rawTagEditor.state = function(_) {
60471         if (!arguments.length) return state;
60472         state = _;
60473         return rawTagEditor;
60474     };
60475
60476
60477     rawTagEditor.preset = function(_) {
60478         if (!arguments.length) return preset;
60479         preset = _;
60480         return rawTagEditor;
60481     };
60482
60483
60484     rawTagEditor.tags = function(_) {
60485         if (!arguments.length) return tags;
60486         tags = _;
60487         return rawTagEditor;
60488     };
60489
60490
60491     rawTagEditor.entityID = function(_) {
60492         if (!arguments.length) return id;
60493         id = _;
60494         return rawTagEditor;
60495     };
60496
60497
60498     return utilRebind(rawTagEditor, dispatch$$1, 'on');
60499 }
60500
60501 function uiFieldCheck(field) {
60502     var dispatch$$1 = dispatch('change'),
60503         options = field.strings && field.strings.options,
60504         values$$1 = [],
60505         texts = [],
60506         box = select(null),
60507         text$$1 = select(null),
60508         label = select(null),
60509         entity, value;
60510
60511     if (options) {
60512         for (var k in options) {
60513             values$$1.push(k === 'undefined' ? undefined : k);
60514             texts.push(field.t('options.' + k, { 'default': options[k] }));
60515         }
60516     } else {
60517         values$$1 = [undefined, 'yes'];
60518         texts = [t('inspector.unknown'), t('inspector.check.yes')];
60519         if (field.type === 'check') {
60520             values$$1.push('no');
60521             texts.push(t('inspector.check.no'));
60522         }
60523     }
60524
60525
60526     var check = function(selection$$1) {
60527         // hack: pretend oneway field is a oneway_yes field
60528         // where implied oneway tag exists (e.g. `junction=roundabout`) #2220, #1841
60529         if (field.id === 'oneway') {
60530             for (var key in entity.tags) {
60531                 if (key in osmOneWayTags && (entity.tags[key] in osmOneWayTags[key])) {
60532                     texts[0] = t('presets.fields.oneway_yes.options.undefined');
60533                     break;
60534                 }
60535             }
60536         }
60537
60538         selection$$1.classed('checkselect', 'true');
60539
60540         label = selection$$1.selectAll('.preset-input-wrap')
60541             .data([0]);
60542
60543         var enter = label.enter()
60544             .append('label')
60545             .attr('class', 'preset-input-wrap');
60546
60547         enter.append('input')
60548             .property('indeterminate', field.type === 'check')
60549             .attr('type', 'checkbox')
60550             .attr('id', 'preset-input-' + field.id)
60551             .on('click', function() {
60552                 var t$$1 = {};
60553                 t$$1[field.key] = values$$1[(values$$1.indexOf(value) + 1) % values$$1.length];
60554                 dispatch$$1.call('change', this, t$$1);
60555                 event.stopPropagation();
60556             });
60557
60558         enter.append('span')
60559             .text(texts[0])
60560             .attr('class', 'value');
60561
60562         label = label.merge(enter);
60563
60564         box = label.selectAll('input');
60565         text$$1 = label.selectAll('span.value');
60566     };
60567
60568
60569     check.entity = function(_) {
60570         if (!arguments.length) return entity;
60571         entity = _;
60572         return check;
60573     };
60574
60575
60576     check.tags = function(tags) {
60577         value = tags[field.key];
60578         box.property('indeterminate', field.type === 'check' && !value);
60579         box.property('checked', value === 'yes');
60580         text$$1.text(texts[values$$1.indexOf(value)]);
60581         label.classed('set', !!value);
60582     };
60583
60584
60585     check.focus = function() {
60586         box.node().focus();
60587     };
60588
60589     return utilRebind(check, dispatch$$1, 'on');
60590 }
60591
60592 function uiFieldCombo(field, context) {
60593     var dispatch$$1 = dispatch('change'),
60594         nominatim = services.nominatim,
60595         taginfo = services.taginfo,
60596         isMulti = (field.type === 'multiCombo'),
60597         isNetwork = (field.type === 'networkCombo'),
60598         optstrings = field.strings && field.strings.options,
60599         optarray = field.options,
60600         snake_case = (field.snake_case || (field.snake_case === undefined)),
60601         combobox = d3combobox().minItems(isMulti ? 1 : 2),
60602         comboData = [],
60603         multiData = [],
60604         container,
60605         input,
60606         entity,
60607         country;
60608
60609     // ensure multiCombo field.key ends with a ':'
60610     if (isMulti && field.key.match(/:$/) === null) {
60611         field.key += ':';
60612     }
60613
60614
60615     function snake(s) {
60616         return s.replace(/\s+/g, '_');
60617     }
60618
60619     function unsnake(s) {
60620         return s.replace(/_+/g, ' ');
60621     }
60622
60623     function clean(s) {
60624         return s.split(';')
60625             .map(function(s) { return s.trim(); })
60626             .join(';');
60627     }
60628
60629
60630     // returns the tag value for a display value
60631     // (for multiCombo, dval should be the key suffix, not the entire key)
60632     function tagValue(dval) {
60633         dval = clean(dval || '');
60634
60635         if (optstrings) {
60636             var match = lodash.find(comboData, function(o) {
60637                 return o.key && clean(o.value) === dval;
60638             });
60639             if (match) {
60640                 return match.key;
60641             }
60642         }
60643
60644         if (field.type === 'typeCombo' && !dval) {
60645             return 'yes';
60646         }
60647
60648         return (snake_case ? snake(dval) : dval) || undefined;
60649     }
60650
60651
60652     // returns the display value for a tag value
60653     // (for multiCombo, tval should be the key suffix, not the entire key)
60654     function displayValue(tval) {
60655         tval = tval || '';
60656
60657         if (optstrings) {
60658             var match = lodash.find(comboData, function(o) { return o.key === tval && o.value; });
60659             if (match) {
60660                 return match.value;
60661             }
60662         }
60663
60664         if (field.type === 'typeCombo' && tval.toLowerCase() === 'yes') {
60665             return '';
60666         }
60667
60668         return snake_case ? unsnake(tval) : tval;
60669     }
60670
60671
60672     function objectDifference(a, b) {
60673         return lodash.reject(a, function(d1) {
60674             return lodash.some(b, function(d2) { return d1.value === d2.value; });
60675         });
60676     }
60677
60678
60679     function initCombo(selection$$1, attachTo) {
60680         if (optstrings) {
60681             selection$$1.attr('readonly', 'readonly');
60682             selection$$1.call(combobox, attachTo);
60683             setStaticValues(setPlaceholder);
60684
60685         } else if (optarray) {
60686             selection$$1.call(combobox, attachTo);
60687             setStaticValues(setPlaceholder);
60688
60689         } else if (taginfo) {
60690             selection$$1.call(combobox.fetcher(setTaginfoValues), attachTo);
60691             setTaginfoValues('', setPlaceholder);
60692         }
60693     }
60694
60695
60696     function setStaticValues(callback) {
60697         if (!(optstrings || optarray)) return;
60698
60699         if (optstrings) {
60700             comboData = Object.keys(optstrings).map(function(k) {
60701                 var v = field.t('options.' + k, { 'default': optstrings[k] });
60702                 return {
60703                     key: k,
60704                     value: v,
60705                     title: v
60706                 };
60707             });
60708
60709         } else if (optarray) {
60710             comboData = optarray.map(function(k) {
60711                 var v = snake_case ? unsnake(k) : k;
60712                 return {
60713                     key: k,
60714                     value: v,
60715                     title: v
60716                 };
60717             });
60718         }
60719
60720         combobox.data(objectDifference(comboData, multiData));
60721         if (callback) callback(comboData);
60722     }
60723
60724
60725     function setTaginfoValues(q, callback) {
60726         var fn = isMulti ? 'multikeys' : 'values';
60727         var query = (isMulti ? field.key : '') + q;
60728         var hasCountryPrefix = isNetwork && country && country.indexOf(q.toLowerCase()) === 0;
60729         if (hasCountryPrefix) {
60730             query = country + ':';
60731         }
60732         taginfo[fn]({
60733             debounce: true,
60734             key: field.key,
60735             geometry: context.geometry(entity.id),
60736             query: query
60737         }, function(err, data) {
60738             if (err) return;
60739             if (hasCountryPrefix) {
60740                 data = lodash.filter(data, function(d) {
60741                     return d.value.toLowerCase().indexOf(country + ':') === 0;
60742                 });
60743             }
60744             comboData = lodash.map(data, function(d) {
60745                 var k = d.value;
60746                 if (isMulti) k = k.replace(field.key, '');
60747                 var v = snake_case ? unsnake(k) : k;
60748                 return {
60749                     key: k,
60750                     value: v,
60751                     title: isMulti ? v : d.title
60752                 };
60753             });
60754             comboData = objectDifference(comboData, multiData);
60755             if (callback) callback(comboData);
60756         });
60757     }
60758
60759
60760     function setPlaceholder(d) {
60761         var ph;
60762         if (isMulti) {
60763             ph = field.placeholder() || t('inspector.add');
60764         } else {
60765             var vals = lodash.map(d, 'value').filter(function(s) { return s.length < 20; }),
60766                 placeholders = vals.length > 1 ? vals : lodash.map(d, 'key');
60767             ph = field.placeholder() || placeholders.slice(0, 3).join(', ');
60768         }
60769
60770         container.selectAll('input')
60771             .attr('placeholder', ph + '…');
60772     }
60773
60774
60775     function change() {
60776         var val = tagValue(utilGetSetValue(input)),
60777             t$$1 = {};
60778
60779         if (isMulti) {
60780             if (!val) return;
60781             container.classed('active', false);
60782             utilGetSetValue(input, '');
60783             field.keys.push(field.key + val);
60784             t$$1[field.key + val] = 'yes';
60785             window.setTimeout(function() { input.node().focus(); }, 10);
60786
60787         } else {
60788             t$$1[field.key] = val;
60789         }
60790
60791         dispatch$$1.call('change', this, t$$1);
60792     }
60793
60794
60795     function removeMultikey(d) {
60796         event.stopPropagation();
60797         var t$$1 = {};
60798         t$$1[d.key] = undefined;
60799         dispatch$$1.call('change', this, t$$1);
60800     }
60801
60802
60803     function combo(selection$$1) {
60804         if (isMulti) {
60805             container = selection$$1.selectAll('ul').data([0]);
60806
60807             container = container.enter()
60808                 .append('ul')
60809                 .attr('class', 'form-field-multicombo')
60810                 .on('click', function() {
60811                     window.setTimeout(function() { input.node().focus(); }, 10);
60812                 })
60813                 .merge(container);
60814
60815         } else {
60816             container = selection$$1;
60817         }
60818
60819         input = container.selectAll('input')
60820             .data([0]);
60821
60822         input = input.enter()
60823             .append('input')
60824             .attr('type', 'text')
60825             .attr('id', 'preset-input-' + field.id)
60826             .call(initCombo, selection$$1)
60827             .merge(input);
60828
60829         if (isNetwork && nominatim && entity) {
60830             var center = entity.extent(context.graph()).center();
60831             nominatim.countryCode(center, function (err, code) {
60832                 country = code;
60833             });
60834         }
60835
60836         input
60837             .on('change', change)
60838             .on('blur', change);
60839
60840         if (isMulti) {
60841             combobox
60842                 .on('accept', function() {
60843                     input.node().blur();
60844                     input.node().focus();
60845                 });
60846
60847             input
60848                 .on('focus', function() { container.classed('active', true); });
60849         }
60850     }
60851
60852
60853     combo.tags = function(tags) {
60854         if (isMulti) {
60855             multiData = [];
60856
60857             // Build multiData array containing keys already set..
60858             Object.keys(tags).forEach(function(key) {
60859                 if (key.indexOf(field.key) !== 0 || tags[key].toLowerCase() !== 'yes') return;
60860
60861                 var suffix = key.substring(field.key.length);
60862                 multiData.push({
60863                     key: key,
60864                     value: displayValue(suffix)
60865                 });
60866             });
60867
60868             // Set keys for form-field modified (needed for undo and reset buttons)..
60869             field.keys = lodash.map(multiData, 'key');
60870
60871             // Exclude existing multikeys from combo options..
60872             var available = objectDifference(comboData, multiData);
60873             combobox.data(available);
60874
60875             // Hide 'Add' button if this field uses fixed set of
60876             // translateable optstrings and they're all currently used..
60877             container.selectAll('.combobox-input, .combobox-caret')
60878                 .classed('hide', optstrings && !available.length);
60879
60880
60881             // Render chips
60882             var chips = container.selectAll('.chips')
60883                 .data(multiData);
60884
60885             chips.exit()
60886                 .remove();
60887
60888             var enter = chips.enter()
60889                 .insert('li', 'input')
60890                 .attr('class', 'chips');
60891
60892             enter.append('span');
60893             enter.append('a');
60894
60895             chips = chips.merge(enter);
60896
60897             chips.select('span')
60898                 .text(function(d) { return d.value; });
60899
60900             chips.select('a')
60901                 .on('click', removeMultikey)
60902                 .attr('class', 'remove')
60903                 .text('×');
60904
60905         } else {
60906             utilGetSetValue(input, displayValue(tags[field.key]));
60907         }
60908     };
60909
60910
60911     combo.focus = function() {
60912         input.node().focus();
60913     };
60914
60915
60916     combo.entity = function(_) {
60917         if (!arguments.length) return entity;
60918         entity = _;
60919         return combo;
60920     };
60921
60922
60923     return utilRebind(combo, dispatch$$1, 'on');
60924 }
60925
60926 function uiFieldText(field, context) {
60927     var dispatch$$1 = dispatch('change'),
60928         nominatim = services.nominatim,
60929         input,
60930         entity;
60931
60932
60933     function i(selection$$1) {
60934         var fieldId = 'preset-input-' + field.id;
60935
60936         input = selection$$1.selectAll('input')
60937             .data([0]);
60938
60939         input = input.enter()
60940             .append('input')
60941             .attr('type', field.type)
60942             .attr('id', fieldId)
60943             .attr('placeholder', field.placeholder() || t('inspector.unknown'))
60944             .merge(input);
60945
60946         input
60947             .on('input', change(true))
60948             .on('blur', change())
60949             .on('change', change());
60950
60951         if (field.type === 'tel' && nominatim && entity) {
60952             var center = entity.extent(context.graph()).center();
60953             nominatim.countryCode(center, function (err, countryCode) {
60954                 if (err || !dataPhoneFormats[countryCode]) return;
60955                 selection$$1.selectAll('#' + fieldId)
60956                     .attr('placeholder', dataPhoneFormats[countryCode]);
60957             });
60958
60959         } else if (field.type === 'number') {
60960             input.attr('type', 'text');
60961
60962             var spinControl = selection$$1.selectAll('.spin-control')
60963                 .data([0]);
60964
60965             var enter = spinControl.enter()
60966                 .append('div')
60967                 .attr('class', 'spin-control');
60968
60969             enter
60970                 .append('button')
60971                 .datum(1)
60972                 .attr('class', 'increment')
60973                 .attr('tabindex', -1);
60974
60975             enter
60976                 .append('button')
60977                 .datum(-1)
60978                 .attr('class', 'decrement')
60979                 .attr('tabindex', -1);
60980
60981             spinControl = spinControl
60982                 .merge(enter);
60983
60984             spinControl.selectAll('button')
60985                 .on('click', function(d) {
60986                     event.preventDefault();
60987                     var num = parseInt(input.node().value || 0, 10);
60988                     if (!isNaN(num)) input.node().value = num + d;
60989                     change()();
60990                 });
60991         }
60992     }
60993
60994
60995     function change(onInput) {
60996         return function() {
60997             var t$$1 = {};
60998             t$$1[field.key] = utilGetSetValue(input) || undefined;
60999             dispatch$$1.call('change', this, t$$1, onInput);
61000         };
61001     }
61002
61003
61004     i.entity = function(_) {
61005         if (!arguments.length) return entity;
61006         entity = _;
61007         return i;
61008     };
61009
61010
61011     i.tags = function(tags) {
61012         utilGetSetValue(input, tags[field.key] || '');
61013     };
61014
61015
61016     i.focus = function() {
61017         var node = input.node();
61018         if (node) node.focus();
61019     };
61020
61021     return utilRebind(i, dispatch$$1, 'on');
61022 }
61023
61024 function uiFieldAccess(field) {
61025     var dispatch$$1 = dispatch('change'),
61026         items;
61027
61028     function access(selection$$1) {
61029         var wrap = selection$$1.selectAll('.preset-input-wrap')
61030             .data([0]);
61031
61032         wrap = wrap.enter()
61033             .append('div')
61034             .attr('class', 'cf preset-input-wrap')
61035             .append('ul')
61036             .merge(wrap);
61037
61038         var list = wrap.selectAll('ul')
61039             .data([0]);
61040
61041         list = list.enter()
61042             .append('ul')
61043             .merge(list);
61044
61045
61046         items = list.selectAll('li')
61047             .data(field.keys);
61048
61049         // Enter
61050         var enter = items.enter()
61051             .append('li')
61052             .attr('class', function(d) { return 'cf preset-access-' + d; });
61053
61054         enter
61055             .append('span')
61056             .attr('class', 'col6 label preset-label-access')
61057             .attr('for', function(d) { return 'preset-input-access-' + d; })
61058             .text(function(d) { return field.t('types.' + d); });
61059
61060         enter
61061             .append('div')
61062             .attr('class', 'col6 preset-input-access-wrap')
61063             .append('input')
61064             .attr('type', 'text')
61065             .attr('class', 'preset-input-access')
61066             .attr('id', function(d) { return 'preset-input-access-' + d; })
61067             .each(function(d) {
61068                 select(this)
61069                     .call(d3combobox()
61070                         .data(access.options(d)));
61071             });
61072
61073
61074         // Update
61075         items = items.merge(enter);
61076
61077         wrap.selectAll('.preset-input-access')
61078             .on('change', change)
61079             .on('blur', change);
61080     }
61081
61082
61083     function change(d) {
61084         var tag = {};
61085         tag[d] = utilGetSetValue(select(this)) || undefined;
61086         dispatch$$1.call('change', this, tag);
61087     }
61088
61089
61090     access.options = function(type) {
61091         var options = ['no', 'permissive', 'private', 'destination'];
61092
61093         if (type !== 'access') {
61094             options.unshift('yes');
61095             options.push('designated');
61096
61097             if (type === 'bicycle') {
61098                 options.push('dismount');
61099             }
61100         }
61101
61102         return options.map(function(option) {
61103             return {
61104                 title: field.t('options.' + option + '.description'),
61105                 value: option
61106             };
61107         });
61108     };
61109
61110
61111     var placeholders = {
61112         footway: {
61113             foot: 'designated',
61114             motor_vehicle: 'no'
61115         },
61116         steps: {
61117             foot: 'yes',
61118             motor_vehicle: 'no',
61119             bicycle: 'no',
61120             horse: 'no'
61121         },
61122         pedestrian: {
61123             foot: 'yes',
61124             motor_vehicle: 'no'
61125         },
61126         cycleway: {
61127             motor_vehicle: 'no',
61128             bicycle: 'designated'
61129         },
61130         bridleway: {
61131             motor_vehicle: 'no',
61132             horse: 'designated'
61133         },
61134         path: {
61135             foot: 'yes',
61136             motor_vehicle: 'no',
61137             bicycle: 'yes',
61138             horse: 'yes'
61139         },
61140         motorway: {
61141             foot: 'no',
61142             motor_vehicle: 'yes',
61143             bicycle: 'no',
61144             horse: 'no'
61145         },
61146         trunk: {
61147             motor_vehicle: 'yes'
61148         },
61149         primary: {
61150             foot: 'yes',
61151             motor_vehicle: 'yes',
61152             bicycle: 'yes',
61153             horse: 'yes'
61154         },
61155         secondary: {
61156             foot: 'yes',
61157             motor_vehicle: 'yes',
61158             bicycle: 'yes',
61159             horse: 'yes'
61160         },
61161         tertiary: {
61162             foot: 'yes',
61163             motor_vehicle: 'yes',
61164             bicycle: 'yes',
61165             horse: 'yes'
61166         },
61167         residential: {
61168             foot: 'yes',
61169             motor_vehicle: 'yes',
61170             bicycle: 'yes',
61171             horse: 'yes'
61172         },
61173         unclassified: {
61174             foot: 'yes',
61175             motor_vehicle: 'yes',
61176             bicycle: 'yes',
61177             horse: 'yes'
61178         },
61179         service: {
61180             foot: 'yes',
61181             motor_vehicle: 'yes',
61182             bicycle: 'yes',
61183             horse: 'yes'
61184         },
61185         motorway_link: {
61186             foot: 'no',
61187             motor_vehicle: 'yes',
61188             bicycle: 'no',
61189             horse: 'no'
61190         },
61191         trunk_link: {
61192             motor_vehicle: 'yes'
61193         },
61194         primary_link: {
61195             foot: 'yes',
61196             motor_vehicle: 'yes',
61197             bicycle: 'yes',
61198             horse: 'yes'
61199         },
61200         secondary_link: {
61201             foot: 'yes',
61202             motor_vehicle: 'yes',
61203             bicycle: 'yes',
61204             horse: 'yes'
61205         },
61206         tertiary_link: {
61207             foot: 'yes',
61208             motor_vehicle: 'yes',
61209             bicycle: 'yes',
61210             horse: 'yes'
61211         }
61212     };
61213
61214
61215     access.tags = function(tags) {
61216         utilGetSetValue(items.selectAll('.preset-input-access'),
61217             function(d) { return tags[d] || ''; })
61218             .attr('placeholder', function() {
61219                 return tags.access ? tags.access : field.placeholder();
61220             });
61221
61222         items.selectAll('#preset-input-access-access')
61223             .attr('placeholder', 'yes');
61224
61225         lodash.forEach(placeholders[tags.highway], function(v, k) {
61226             items.selectAll('#preset-input-access-' + k)
61227                 .attr('placeholder', function() { return (tags.access || v); });
61228         });
61229     };
61230
61231
61232     access.focus = function() {
61233         items.selectAll('.preset-input-access')
61234             .node().focus();
61235     };
61236
61237
61238     return utilRebind(access, dispatch$$1, 'on');
61239 }
61240
61241 function uiFieldAddress(field, context) {
61242     var dispatch$$1 = dispatch('init', 'change'),
61243         nominatim = services.nominatim,
61244         wrap = select(null),
61245         isInitialized = false,
61246         entity;
61247
61248     var widths = {
61249         housenumber: 1/3,
61250         street: 2/3,
61251         city: 2/3,
61252         state: 1/4,
61253         postcode: 1/3
61254     };
61255
61256
61257     function getNearStreets() {
61258         var extent$$1 = entity.extent(context.graph()),
61259             l = extent$$1.center(),
61260             box = geoExtent$$1(l).padByMeters(200);
61261
61262         var streets = context.intersects(box)
61263             .filter(isAddressable)
61264             .map(function(d) {
61265                 var loc = context.projection([
61266                     (extent$$1[0][0] + extent$$1[1][0]) / 2,
61267                     (extent$$1[0][1] + extent$$1[1][1]) / 2]),
61268                     choice = geoChooseEdge(context.childNodes(d), loc, context.projection);
61269                 return {
61270                     title: d.tags.name,
61271                     value: d.tags.name,
61272                     dist: choice.distance
61273                 };
61274             })
61275             .sort(function(a, b) {
61276                 return a.dist - b.dist;
61277             });
61278
61279         return lodash.uniqBy(streets, 'value');
61280
61281         function isAddressable(d) {
61282             return d.tags.highway && d.tags.name && d.type === 'way';
61283         }
61284     }
61285
61286
61287     function getNearCities() {
61288         var extent$$1 = entity.extent(context.graph()),
61289             l = extent$$1.center(),
61290             box = geoExtent$$1(l).padByMeters(200);
61291
61292         var cities = context.intersects(box)
61293             .filter(isAddressable)
61294             .map(function(d) {
61295                 return {
61296                     title: d.tags['addr:city'] || d.tags.name,
61297                     value: d.tags['addr:city'] || d.tags.name,
61298                     dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
61299                 };
61300             })
61301             .sort(function(a, b) {
61302                 return a.dist - b.dist;
61303             });
61304
61305         return lodash.uniqBy(cities, 'value');
61306
61307
61308         function isAddressable(d) {
61309             if (d.tags.name &&
61310                 (d.tags.admin_level === '8' || d.tags.border_type === 'city'))
61311                 return true;
61312
61313             if (d.tags.place && d.tags.name && (
61314                     d.tags.place === 'city' ||
61315                     d.tags.place === 'town' ||
61316                     d.tags.place === 'village'))
61317                 return true;
61318
61319             if (d.tags['addr:city']) return true;
61320
61321             return false;
61322         }
61323     }
61324
61325
61326     function getNearValues(key) {
61327         var extent$$1 = entity.extent(context.graph()),
61328             l = extent$$1.center(),
61329             box = geoExtent$$1(l).padByMeters(200);
61330
61331         var results = context.intersects(box)
61332             .filter(function hasTag(d) {
61333                 return d.tags[key];
61334             })
61335             .map(function(d) {
61336                 return {
61337                     title: d.tags[key],
61338                     value: d.tags[key],
61339                     dist: geoSphericalDistance(d.extent(context.graph()).center(), l)
61340                 };
61341             })
61342             .sort(function(a, b) {
61343                 return a.dist - b.dist;
61344             });
61345
61346         return lodash.uniqBy(results, 'value');
61347     }
61348
61349
61350     function initCallback(err, countryCode) {
61351         if (err) return;
61352
61353         var addressFormat = lodash.find(dataAddressFormats, function (a) {
61354             return a && a.countryCodes && lodash.includes(a.countryCodes, countryCode);
61355         }) || lodash.first(dataAddressFormats);
61356
61357         function row(r) {
61358             // Normalize widths.
61359             var total = lodash.reduce(r, function(sum$$1, field) {
61360                 return sum$$1 + (widths[field] || 0.5);
61361             }, 0);
61362
61363             return r.map(function (field) {
61364                 return {
61365                     id: field,
61366                     width: (widths[field] || 0.5) / total
61367                 };
61368             });
61369         }
61370
61371         wrap.selectAll('div')
61372             .data(addressFormat.format)
61373             .enter()
61374             .append('div')
61375             .attr('class', 'addr-row')
61376             .selectAll('input')
61377             .data(row)
61378             .enter()
61379             .append('input')
61380             .property('type', 'text')
61381             .attr('placeholder', function (d) { return field.t('placeholders.' + d.id); })
61382             .attr('class', function (d) { return 'addr-' + d.id; })
61383             .style('width', function (d) { return d.width * 100 + '%'; });
61384
61385         // Update
61386         // setup dropdowns for common address tags
61387         var addrTags = [
61388             'street', 'city', 'state', 'province', 'district',
61389             'subdistrict', 'suburb', 'place', 'postcode'
61390         ];
61391
61392         addrTags.forEach(function(tag) {
61393             var nearValues = (tag === 'street') ? getNearStreets
61394                     : (tag === 'city') ? getNearCities
61395                     : getNearValues;
61396
61397             wrap.selectAll('.addr-' + tag)
61398                 .call(d3combobox()
61399                     .minItems(1)
61400                     .fetcher(function(value, callback) {
61401                         callback(nearValues('addr:' + tag));
61402                     }));
61403         });
61404
61405         wrap.selectAll('input')
61406             .on('blur', change())
61407             .on('change', change());
61408
61409         wrap.selectAll('input:not(.combobox-input)')
61410             .on('input', change(true));
61411
61412         dispatch$$1.call('init');
61413         isInitialized = true;
61414     }
61415
61416
61417     function address(selection$$1) {
61418         isInitialized = false;
61419
61420         wrap = selection$$1.selectAll('.preset-input-wrap')
61421             .data([0]);
61422
61423         wrap = wrap.enter()
61424             .append('div')
61425             .attr('class', 'preset-input-wrap')
61426             .merge(wrap);
61427
61428
61429         if (nominatim && entity) {
61430             var center = entity.extent(context.graph()).center();
61431             nominatim.countryCode(center, initCallback);
61432         }
61433     }
61434
61435
61436     function change(onInput) {
61437         return function() {
61438             var tags = {};
61439
61440             wrap.selectAll('input')
61441                 .each(function (field) {
61442                     tags['addr:' + field.id] = this.value || undefined;
61443                 });
61444
61445             dispatch$$1.call('change', this, tags, onInput);
61446         };
61447     }
61448
61449
61450     function updateTags(tags) {
61451         utilGetSetValue(wrap.selectAll('input'), function (field) {
61452             return tags['addr:' + field.id] || '';
61453         });
61454     }
61455
61456
61457     address.entity = function(_) {
61458         if (!arguments.length) return entity;
61459         entity = _;
61460         return address;
61461     };
61462
61463
61464     address.tags = function(tags) {
61465         if (isInitialized) {
61466             updateTags(tags);
61467         } else {
61468             dispatch$$1.on('init', function () {
61469                 updateTags(tags);
61470             });
61471         }
61472     };
61473
61474
61475     address.focus = function() {
61476         var node = wrap.selectAll('input').node();
61477         if (node) node.focus();
61478     };
61479
61480
61481     return utilRebind(address, dispatch$$1, 'on');
61482 }
61483
61484 function uiFieldCycleway(field) {
61485     var dispatch$$1 = dispatch('change'),
61486         items = select(null);
61487
61488
61489     function cycleway(selection$$1) {
61490
61491         function stripcolon(s) {
61492             return s.replace(':', '');
61493         }
61494
61495
61496         var wrap = selection$$1.selectAll('.preset-input-wrap')
61497             .data([0]);
61498
61499         wrap = wrap.enter()
61500             .append('div')
61501             .attr('class', 'cf preset-input-wrap')
61502             .merge(wrap);
61503
61504
61505         var div = wrap.selectAll('ul')
61506             .data([0]);
61507
61508         div = div.enter()
61509             .append('ul')
61510             .merge(div);
61511
61512
61513         items = div.selectAll('li')
61514             .data(field.keys);
61515
61516         var enter = items.enter()
61517             .append('li')
61518             .attr('class', function(d) { return 'cf preset-cycleway-' + stripcolon(d); });
61519
61520         enter
61521             .append('span')
61522             .attr('class', 'col6 label preset-label-cycleway')
61523             .attr('for', function(d) { return 'preset-input-cycleway-' + stripcolon(d); })
61524             .text(function(d) { return field.t('types.' + d); });
61525
61526         enter
61527             .append('div')
61528             .attr('class', 'col6 preset-input-cycleway-wrap')
61529             .append('input')
61530             .attr('type', 'text')
61531             .attr('class', function(d) { return 'preset-input-cycleway preset-input-' + stripcolon(d); })
61532             .each(function(d) {
61533                 select(this).call(d3combobox().data(cycleway.options(d)));
61534             });
61535
61536
61537         // Update
61538         wrap.selectAll('.preset-input-cycleway')
61539             .on('change', change)
61540             .on('blur', change);
61541     }
61542
61543
61544     function change() {
61545         var left = utilGetSetValue(select('.preset-input-cyclewayleft')),
61546             right = utilGetSetValue(select('.preset-input-cyclewayright')),
61547             tag = {};
61548
61549         if (left === 'none' || left === '') { left = undefined; }
61550         if (right === 'none' || right === '') { right = undefined; }
61551
61552         // Always set both left and right as changing one can affect the other
61553         tag = {
61554             cycleway: undefined,
61555             'cycleway:left': left,
61556             'cycleway:right': right
61557         };
61558
61559         // If the left and right tags match, use the cycleway tag to tag both
61560         // sides the same way
61561         if (left === right) {
61562             tag = {
61563                 cycleway: left,
61564                 'cycleway:left': undefined,
61565                 'cycleway:right': undefined
61566             };
61567         }
61568
61569         dispatch$$1.call('change', this, tag);
61570     }
61571
61572
61573     cycleway.options = function() {
61574         return keys(field.strings.options).map(function(option) {
61575             return {
61576                 title: field.t('options.' + option + '.description'),
61577                 value: option
61578             };
61579         });
61580     };
61581
61582
61583     cycleway.tags = function(tags) {
61584         utilGetSetValue(items.selectAll('.preset-input-cycleway'), function(d) {
61585                 // If cycleway is set, always return that
61586                 if (tags.cycleway) {
61587                     return tags.cycleway;
61588                 }
61589                 return tags[d] || '';
61590             })
61591             .attr('placeholder', field.placeholder());
61592     };
61593
61594
61595     cycleway.focus = function() {
61596         items.selectAll('.preset-input-cycleway')
61597             .node().focus();
61598     };
61599
61600
61601     return utilRebind(cycleway, dispatch$$1, 'on');
61602 }
61603
61604 function uiFieldLanes(field, context) {
61605     var dispatch$$1 = dispatch('change'),
61606         LANE_WIDTH = 40,
61607         LANE_HEIGHT = 200,
61608         wayID,
61609         lanesData;
61610
61611     function lanes(selection$$1) {
61612         lanesData = context.entity(wayID).lanes();
61613
61614         if (!select('.inspector-wrap.inspector-hidden').empty() || !selection$$1.node().parentNode) {
61615             selection$$1.call(lanes.off);
61616             return;
61617         }
61618
61619         var wrap = selection$$1.selectAll('.preset-input-wrap')
61620             .data([0]);
61621
61622         wrap = wrap.enter()
61623             .append('div')
61624             .attr('class', 'preset-input-wrap')
61625             .merge(wrap);
61626
61627         var surface =  wrap.selectAll('.surface')
61628             .data([0]);
61629
61630         var d = utilGetDimensions(wrap);
61631         var freeSpace = d[0] - lanesData.lanes.length * LANE_WIDTH * 1.5 + LANE_WIDTH * 0.5;
61632
61633         surface = surface.enter()
61634             .append('svg')
61635             .attr('width', d[0])
61636             .attr('height', 300)
61637             .attr('class', 'surface')
61638             .merge(surface);
61639
61640
61641         var lanesSelection = surface.selectAll('.lanes')
61642             .data([0]);
61643
61644         lanesSelection = lanesSelection.enter()
61645             .append('g')
61646             .attr('class', 'lanes')
61647             .merge(lanesSelection);
61648
61649         lanesSelection
61650             .attr('transform', function () {
61651                 return 'translate(' + (freeSpace / 2) + ', 0)';
61652             });
61653
61654
61655         var lane = lanesSelection.selectAll('.lane')
61656            .data(lanesData.lanes);
61657
61658         lane.exit()
61659             .remove();
61660
61661         var enter = lane.enter()
61662             .append('g')
61663             .attr('class', 'lane');
61664
61665         enter
61666             .append('g')
61667             .append('rect')
61668             .attr('y', 50)
61669             .attr('width', LANE_WIDTH)
61670             .attr('height', LANE_HEIGHT);
61671
61672         enter
61673             .append('g')
61674             .attr('class', 'forward')
61675             .append('text')
61676             .attr('y', 40)
61677             .attr('x', 14)
61678             .text('▲');
61679
61680         enter
61681             .append('g')
61682             .attr('class', 'bothways')
61683             .append('text')
61684             .attr('y', 40)
61685             .attr('x', 14)
61686             .text('▲▼');
61687
61688         enter
61689             .append('g')
61690             .attr('class', 'backward')
61691             .append('text')
61692             .attr('y', 40)
61693             .attr('x', 14)
61694             .text('▼');
61695
61696
61697         lane = lane
61698             .merge(enter);
61699
61700         lane
61701             .attr('transform', function(d) {
61702                 return 'translate(' + (LANE_WIDTH * d.index * 1.5) + ', 0)';
61703             });
61704
61705         lane.select('.forward')
61706             .style('visibility', function(d) {
61707                 return d.direction === 'forward' ? 'visible' : 'hidden';
61708             });
61709
61710         lane.select('.bothways')
61711             .style('visibility', function(d) {
61712                 return d.direction === 'bothways' ? 'visible' : 'hidden';
61713             });
61714
61715         lane.select('.backward')
61716             .style('visibility', function(d) {
61717                 return d.direction === 'backward' ? 'visible' : 'hidden';
61718             });
61719     }
61720
61721
61722     lanes.entity = function(_) {
61723         if (!wayID || wayID !== _.id) {
61724             wayID = _.id;
61725         }
61726     };
61727
61728     lanes.tags = function() {};
61729     lanes.focus = function() {};
61730     lanes.off = function() {};
61731
61732     return utilRebind(lanes, dispatch$$1, 'on');
61733 }
61734
61735 function uiFieldLocalized(field, context) {
61736     var dispatch$$1 = dispatch('change', 'input'),
61737         wikipedia = services.wikipedia,
61738         input = select(null),
61739         localizedInputs = select(null),
61740         wikiTitles,
61741         entity;
61742
61743
61744     function localized(selection$$1) {
61745         input = selection$$1.selectAll('.localized-main')
61746             .data([0]);
61747
61748         input = input.enter()
61749             .append('input')
61750             .attr('type', 'text')
61751             .attr('id', 'preset-input-' + field.id)
61752             .attr('class', 'localized-main')
61753             .attr('placeholder', field.placeholder())
61754             .merge(input);
61755
61756         if (field.id === 'name') {
61757             var preset = context.presets().match(entity, context.graph());
61758             input.call(d3combobox().fetcher(
61759                 utilSuggestNames(preset, dataSuggestions)
61760             ));
61761         }
61762
61763         input
61764             .on('input', change(true))
61765             .on('blur', change())
61766             .on('change', change());
61767
61768
61769         var translateButton = selection$$1.selectAll('.localized-add')
61770             .data([0]);
61771
61772         translateButton = translateButton.enter()
61773             .append('button')
61774             .attr('class', 'button-input-action localized-add minor')
61775             .attr('tabindex', -1)
61776             .call(svgIcon('#icon-plus'))
61777             .call(tooltip()
61778                 .title(t('translate.translate'))
61779                 .placement('left'))
61780             .merge(translateButton);
61781
61782         translateButton
61783             .on('click', addNew);
61784
61785
61786         localizedInputs = selection$$1.selectAll('.localized-wrap')
61787             .data([0]);
61788
61789         localizedInputs = localizedInputs.enter().append('div')
61790             .attr('class', 'localized-wrap')
61791             .merge(localizedInputs);
61792     }
61793
61794
61795     function addNew() {
61796         event.preventDefault();
61797         var data$$1 = localizedInputs.selectAll('div.entry').data();
61798         var defaultLang = utilDetect().locale.toLowerCase().split('-')[0];
61799         var langExists = lodash.find(data$$1, function(datum) { return datum.lang === defaultLang;});
61800         var isLangEn = defaultLang.indexOf('en') > -1;
61801         if (isLangEn || langExists) {
61802             defaultLang = '';
61803         }
61804         data$$1.push({ lang: defaultLang, value: '' });
61805         localizedInputs.call(render, data$$1);
61806     }
61807
61808
61809     function change(onInput) {
61810         return function() {
61811             var t$$1 = {};
61812             t$$1[field.key] = utilGetSetValue(select(this)) || undefined;
61813             dispatch$$1.call('change', this, t$$1, onInput);
61814         };
61815     }
61816
61817
61818     function key(lang) {
61819         return field.key + ':' + lang;
61820     }
61821
61822
61823     function changeLang(d) {
61824         var lang = utilGetSetValue(select(this)),
61825             t$$1 = {},
61826             language = lodash.find(dataWikipedia, function(d) {
61827                 return d[0].toLowerCase() === lang.toLowerCase() ||
61828                     d[1].toLowerCase() === lang.toLowerCase();
61829             });
61830
61831         if (language) lang = language[2];
61832
61833         if (d.lang && d.lang !== lang) {
61834             t$$1[key(d.lang)] = undefined;
61835         }
61836
61837         var value = utilGetSetValue(select(this.parentNode)
61838             .selectAll('.localized-value'));
61839
61840         if (lang && value) {
61841             t$$1[key(lang)] = value;
61842         } else if (lang && wikiTitles && wikiTitles[d.lang]) {
61843             t$$1[key(lang)] = wikiTitles[d.lang];
61844         }
61845
61846         d.lang = lang;
61847         dispatch$$1.call('change', this, t$$1);
61848     }
61849
61850
61851     function changeValue(d) {
61852         if (!d.lang) return;
61853         var t$$1 = {};
61854         t$$1[key(d.lang)] = utilGetSetValue(select(this)) || undefined;
61855         dispatch$$1.call('change', this, t$$1);
61856     }
61857
61858
61859     function fetcher(value, cb) {
61860         var v = value.toLowerCase();
61861
61862         cb(dataWikipedia.filter(function(d) {
61863             return d[0].toLowerCase().indexOf(v) >= 0 ||
61864             d[1].toLowerCase().indexOf(v) >= 0 ||
61865             d[2].toLowerCase().indexOf(v) >= 0;
61866         }).map(function(d) {
61867             return { value: d[1] };
61868         }));
61869     }
61870
61871
61872     function render(selection$$1, data$$1) {
61873         var wraps = selection$$1.selectAll('div.entry').
61874             data(data$$1, function(d) { return d.lang; });
61875
61876         wraps.exit()
61877             .transition()
61878             .duration(200)
61879             .style('max-height','0px')
61880             .style('opacity', '0')
61881             .style('top','-10px')
61882             .remove();
61883
61884         var innerWrap = wraps.enter()
61885             .insert('div', ':first-child');
61886
61887         innerWrap.attr('class', 'entry')
61888             .each(function() {
61889                 var wrap = select(this);
61890                 var langcombo = d3combobox().fetcher(fetcher).minItems(0);
61891
61892                 var label = wrap
61893                     .append('label')
61894                     .attr('class','form-label')
61895                     .text(t('translate.localized_translation_label'))
61896                     .attr('for','localized-lang');
61897
61898                 label
61899                     .append('button')
61900                     .attr('class', 'minor remove')
61901                     .on('click', function(d){
61902                         event.preventDefault();
61903                         var t$$1 = {};
61904                         t$$1[key(d.lang)] = undefined;
61905                         dispatch$$1.call('change', this, t$$1);
61906                         select(this.parentNode.parentNode)
61907                             .style('top','0')
61908                             .style('max-height','240px')
61909                             .transition()
61910                             .style('opacity', '0')
61911                             .style('max-height','0px')
61912                             .remove();
61913                     })
61914                     .call(svgIcon('#operation-delete'));
61915
61916                 wrap
61917                     .append('input')
61918                     .attr('class', 'localized-lang')
61919                     .attr('type', 'text')
61920                     .attr('placeholder',t('translate.localized_translation_language'))
61921                     .on('blur', changeLang)
61922                     .on('change', changeLang)
61923                     .call(langcombo);
61924
61925                 wrap
61926                     .append('input')
61927                     .on('blur', changeValue)
61928                     .on('change', changeValue)
61929                     .attr('type', 'text')
61930                     .attr('placeholder', t('translate.localized_translation_name'))
61931                     .attr('class', 'localized-value');
61932             });
61933
61934         innerWrap
61935             .style('margin-top', '0px')
61936             .style('max-height', '0px')
61937             .style('opacity', '0')
61938             .transition()
61939             .duration(200)
61940             .style('margin-top', '10px')
61941             .style('max-height', '240px')
61942             .style('opacity', '1')
61943             .on('end', function() {
61944                 select(this)
61945                     .style('max-height', '')
61946                     .style('overflow', 'visible');
61947             });
61948
61949
61950         var entry = selection$$1.selectAll('.entry');
61951
61952         utilGetSetValue(entry.select('.localized-lang'), function(d) {
61953                 var lang = lodash.find(dataWikipedia, function(lang) { return lang[2] === d.lang; });
61954                 return lang ? lang[1] : d.lang;
61955             });
61956
61957         utilGetSetValue(entry.select('.localized-value'),
61958             function(d) { return d.value; });
61959     }
61960
61961
61962     localized.tags = function(tags) {
61963         // Fetch translations from wikipedia
61964         if (tags.wikipedia && !wikiTitles) {
61965             wikiTitles = {};
61966             var wm = tags.wikipedia.match(/([^:]+):(.+)/);
61967             if (wm && wm[0] && wm[1]) {
61968                 wikipedia.translations(wm[1], wm[2], function(d) {
61969                     wikiTitles = d;
61970                 });
61971             }
61972         }
61973
61974         utilGetSetValue(input, tags[field.key] || '');
61975
61976         var postfixed = [], k, m;
61977         for (k in tags) {
61978             m = k.match(/^(.*):([a-zA-Z_-]+)$/);
61979             if (m && m[1] === field.key && m[2]) {
61980                 postfixed.push({ lang: m[2], value: tags[k] });
61981             }
61982         }
61983
61984         localizedInputs.call(render, postfixed.reverse());
61985     };
61986
61987
61988     localized.focus = function() {
61989         input.node().focus();
61990     };
61991
61992
61993     localized.entity = function(_) {
61994         if (!arguments.length) return entity;
61995         entity = _;
61996         return localized;
61997     };
61998
61999     return utilRebind(localized, dispatch$$1, 'on');
62000 }
62001
62002 function uiFieldMaxspeed(field, context) {
62003     var dispatch$$1 = dispatch('change'),
62004         entity,
62005         isImperial,
62006         unitInput = select(null),
62007         input = select(null),
62008         combobox;
62009
62010     var metricValues = [20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120],
62011         imperialValues = [5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80];
62012
62013
62014     function maxspeed(selection$$1) {
62015         combobox = d3combobox();
62016         var unitCombobox = d3combobox().data(['km/h', 'mph'].map(comboValues));
62017
62018         input = selection$$1.selectAll('#preset-input-' + field.id)
62019             .data([0]);
62020
62021         input = input.enter()
62022             .append('input')
62023             .attr('type', 'text')
62024             .attr('id', 'preset-input-' + field.id)
62025             .attr('placeholder', field.placeholder())
62026             .call(combobox)
62027             .merge(input);
62028
62029         input
62030             .on('change', change)
62031             .on('blur', change);
62032
62033         var childNodes = context.graph().childNodes(context.entity(entity.id)),
62034             loc = childNodes[~~(childNodes.length/2)].loc;
62035
62036         isImperial = lodash.some(dataImperial.features, function(f) {
62037             return lodash.some(f.geometry.coordinates, function(d) {
62038                 return geoPointInPolygon(loc, d);
62039             });
62040         });
62041
62042         unitInput = selection$$1.selectAll('input.maxspeed-unit')
62043             .data([0]);
62044
62045         unitInput = unitInput.enter()
62046             .append('input')
62047             .attr('type', 'text')
62048             .attr('class', 'maxspeed-unit')
62049             .call(unitCombobox)
62050             .merge(unitInput);
62051
62052         unitInput
62053             .on('blur', changeUnits)
62054             .on('change', changeUnits);
62055
62056
62057         function changeUnits() {
62058             isImperial = utilGetSetValue(unitInput) === 'mph';
62059             utilGetSetValue(unitInput, isImperial ? 'mph' : 'km/h');
62060             setSuggestions();
62061             change();
62062         }
62063     }
62064
62065
62066     function setSuggestions() {
62067         combobox.data((isImperial ? imperialValues : metricValues).map(comboValues));
62068         utilGetSetValue(unitInput, isImperial ? 'mph' : 'km/h');
62069     }
62070
62071
62072     function comboValues(d) {
62073         return {
62074             value: d.toString(),
62075             title: d.toString()
62076         };
62077     }
62078
62079
62080     function change() {
62081         var tag = {},
62082             value = utilGetSetValue(input);
62083
62084         if (!value) {
62085             tag[field.key] = undefined;
62086         } else if (isNaN(value) || !isImperial) {
62087             tag[field.key] = value;
62088         } else {
62089             tag[field.key] = value + ' mph';
62090         }
62091
62092         dispatch$$1.call('change', this, tag);
62093     }
62094
62095
62096     maxspeed.tags = function(tags) {
62097         var value = tags[field.key];
62098
62099         if (value && value.indexOf('mph') >= 0) {
62100             value = parseInt(value, 10);
62101             isImperial = true;
62102         } else if (value) {
62103             isImperial = false;
62104         }
62105
62106         setSuggestions();
62107         utilGetSetValue(input, value || '');
62108     };
62109
62110
62111     maxspeed.focus = function() {
62112         input.node().focus();
62113     };
62114
62115
62116     maxspeed.entity = function(_) {
62117         entity = _;
62118     };
62119
62120
62121     return utilRebind(maxspeed, dispatch$$1, 'on');
62122 }
62123
62124 function uiFieldRadio(field) {
62125     var dispatch$$1 = dispatch('change'),
62126         placeholder = select(null),
62127         labels = select(null),
62128         radios = select(null);
62129
62130
62131     function radio(selection$$1) {
62132         selection$$1.classed('preset-radio', true);
62133
62134         var wrap = selection$$1.selectAll('.preset-input-wrap')
62135             .data([0]);
62136
62137         var enter = wrap.enter()
62138             .append('div')
62139             .attr('class', 'preset-input-wrap toggle-list');
62140
62141         enter
62142             .append('span')
62143             .attr('class', 'placeholder');
62144
62145         wrap = wrap
62146             .merge(enter);
62147
62148
62149         placeholder = wrap.selectAll('.placeholder');
62150
62151         labels = wrap.selectAll('label')
62152             .data(field.options || field.keys);
62153
62154         enter = labels.enter()
62155             .append('label');
62156
62157         enter.append('input')
62158             .attr('type', 'radio')
62159             .attr('name', field.id)
62160             .attr('value', function(d) { return field.t('options.' + d, { 'default': d }); })
62161             .attr('checked', false);
62162
62163         enter.append('span')
62164             .text(function(d) { return field.t('options.' + d, { 'default': d }); });
62165
62166         labels = labels
62167             .merge(enter);
62168
62169         radios = labels.selectAll('input')
62170             .on('change', change);
62171     }
62172
62173
62174     function change() {
62175         var t$$1 = {};
62176         if (field.key) t$$1[field.key] = undefined;
62177         radios.each(function(d) {
62178             var active$$1 = select(this).property('checked');
62179             if (field.key) {
62180                 if (active$$1) t$$1[field.key] = d;
62181             } else {
62182                 t$$1[d] = active$$1 ? 'yes' : undefined;
62183             }
62184         });
62185         dispatch$$1.call('change', this, t$$1);
62186     }
62187
62188
62189     radio.tags = function(tags) {
62190         function checked(d) {
62191             if (field.key) {
62192                 return tags[field.key] === d;
62193             } else {
62194                 return !!(tags[d] && tags[d] !== 'no');
62195             }
62196         }
62197
62198         labels.classed('active', checked);
62199         radios.property('checked', checked);
62200         var selection$$1 = radios.filter(function() { return this.checked; });
62201         if (selection$$1.empty()) {
62202             placeholder.text(t('inspector.none'));
62203         } else {
62204             placeholder.text(selection$$1.attr('value'));
62205         }
62206     };
62207
62208
62209     radio.focus = function() {
62210         radios.node().focus();
62211     };
62212
62213
62214     return utilRebind(radio, dispatch$$1, 'on');
62215 }
62216
62217 function uiFieldRestrictions(field, context) {
62218     var dispatch$$1 = dispatch('change'),
62219         breathe = behaviorBreathe(context),
62220         hover = behaviorHover(context),
62221         initialized = false,
62222         vertexID,
62223         fromNodeID;
62224
62225
62226     function restrictions(selection$$1) {
62227         // if form field is hidden or has detached from dom, clean up.
62228         if (!select('.inspector-wrap.inspector-hidden').empty() || !selection$$1.node().parentNode) {
62229             selection$$1.call(restrictions.off);
62230             return;
62231         }
62232
62233         var wrap = selection$$1.selectAll('.preset-input-wrap')
62234             .data([0]);
62235
62236         var enter = wrap.enter()
62237             .append('div')
62238             .attr('class', 'preset-input-wrap');
62239
62240         enter
62241             .append('div')
62242             .attr('class', 'restriction-help');
62243
62244
62245         var intersection = osmIntersection(context.graph(), vertexID),
62246             graph = intersection.graph,
62247             vertex = graph.entity(vertexID),
62248             filter = utilFunctor(true),
62249             extent$$1 = geoExtent$$1(),
62250             projection = geoRawMercator();
62251
62252         var d = utilGetDimensions(wrap.merge(enter)),
62253             c = [d[0] / 2, d[1] / 2],
62254             z = 24;
62255
62256         projection
62257             .scale(256 * Math.pow(2, z) / (2 * Math.PI));
62258
62259         var s = projection(vertex.loc);
62260
62261         projection
62262             .translate([c[0] - s[0], c[1] - s[1]])
62263             .clipExtent([[0, 0], d]);
62264
62265         var drawLayers = svgLayers(projection, context).only('osm').dimensions(d),
62266             drawVertices = svgVertices$$1(projection, context),
62267             drawLines = svgLines$$1(projection, context),
62268             drawTurns = svgTurns(projection, context);
62269
62270         enter
62271             .call(drawLayers);
62272
62273         wrap = wrap
62274             .merge(enter);
62275
62276         var surface = wrap.selectAll('.surface');
62277
62278         if (!enter.empty()) {
62279             initialized = true;
62280             surface
62281                 .call(breathe)
62282                 .call(hover);
62283         }
62284
62285         surface
62286             .call(utilSetDimensions, d)
62287             .call(drawVertices, graph, [vertex], filter, extent$$1, z)
62288             .call(drawLines, graph, intersection.ways, filter)
62289             .call(drawTurns, graph, intersection.turns(fromNodeID));
62290
62291         surface
62292             .on('click.restrictions', click)
62293             .on('mouseover.restrictions', mouseover)
62294             .on('mouseout.restrictions', mouseout);
62295
62296         surface
62297             .selectAll('.selected')
62298             .classed('selected', false);
62299
62300         if (fromNodeID) {
62301             surface
62302                 .selectAll('.' + intersection.highways[fromNodeID].id)
62303                 .classed('selected', true);
62304         }
62305
62306         mouseout();
62307
62308         context.history()
62309             .on('change.restrictions', render);
62310
62311         select(window)
62312             .on('resize.restrictions', function() {
62313                 utilSetDimensions(wrap, null);
62314                 render();
62315             });
62316
62317
62318         function click() {
62319             surface
62320                 .call(breathe.off)
62321                 .call(breathe);
62322
62323             var datum = event.target.__data__;
62324             if (datum instanceof osmEntity$$1) {
62325                 fromNodeID = intersection.adjacentNodeId(datum.id);
62326                 render();
62327             } else if (datum instanceof osmTurn) {
62328                 if (datum.restriction) {
62329                     context.perform(
62330                         actionUnrestrictTurn(datum, projection),
62331                         t('operations.restriction.annotation.delete')
62332                     );
62333                 } else {
62334                     context.perform(
62335                         actionRestrictTurn(datum, projection),
62336                         t('operations.restriction.annotation.create')
62337                     );
62338                 }
62339             }
62340         }
62341
62342
62343         function mouseover() {
62344             var datum = event.target.__data__;
62345             if (datum instanceof osmTurn) {
62346                 var graph = context.graph(),
62347                     presets = context.presets(),
62348                     preset;
62349
62350                 if (datum.restriction) {
62351                     preset = presets.match(graph.entity(datum.restriction), graph);
62352                 } else {
62353                     preset = presets.item('type/restriction/' +
62354                         osmInferRestriction(
62355                             graph,
62356                             datum.from,
62357                             datum.via,
62358                             datum.to,
62359                             projection
62360                         )
62361                     );
62362                 }
62363
62364                 wrap.selectAll('.restriction-help')
62365                     .text(t('operations.restriction.help.' +
62366                         (datum.restriction ? 'toggle_off' : 'toggle_on'),
62367                         { restriction: preset.name() })
62368                     );
62369             }
62370         }
62371
62372
62373         function mouseout() {
62374             wrap.selectAll('.restriction-help')
62375                 .text(t('operations.restriction.help.' +
62376                     (fromNodeID ? 'toggle' : 'select'))
62377                 );
62378         }
62379
62380
62381         function render() {
62382             if (context.hasEntity(vertexID)) {
62383                 restrictions(selection$$1);
62384             }
62385         }
62386     }
62387
62388
62389     restrictions.entity = function(_) {
62390         if (!vertexID || vertexID !== _.id) {
62391             fromNodeID = null;
62392             vertexID = _.id;
62393         }
62394     };
62395
62396
62397     restrictions.tags = function() {};
62398     restrictions.focus = function() {};
62399
62400
62401     restrictions.off = function(selection$$1) {
62402         if (!initialized) return;
62403
62404         selection$$1.selectAll('.surface')
62405             .call(hover.off)
62406             .call(breathe.off)
62407             .on('click.restrictions', null)
62408             .on('mouseover.restrictions', null)
62409             .on('mouseout.restrictions', null);
62410
62411         context.history()
62412             .on('change.restrictions', null);
62413
62414         select(window)
62415             .on('resize.restrictions', null);
62416     };
62417
62418
62419     return utilRebind(restrictions, dispatch$$1, 'on');
62420 }
62421
62422 function uiFieldTextarea(field) {
62423     var dispatch$$1 = dispatch('change'),
62424         input = select(null);
62425
62426
62427     function textarea(selection$$1) {
62428         input = selection$$1.selectAll('textarea')
62429             .data([0]);
62430
62431         input = input.enter()
62432             .append('textarea')
62433             .attr('id', 'preset-input-' + field.id)
62434             .attr('placeholder', field.placeholder() || t('inspector.unknown'))
62435             .attr('maxlength', 255)
62436             .on('input', change(true))
62437             .on('blur', change())
62438             .on('change', change())
62439             .merge(input);
62440     }
62441
62442
62443     function change(onInput) {
62444         return function() {
62445             var t$$1 = {};
62446             t$$1[field.key] = utilGetSetValue(input) || undefined;
62447             dispatch$$1.call('change', this, t$$1, onInput);
62448         };
62449     }
62450
62451
62452     textarea.tags = function(tags) {
62453         utilGetSetValue(input, tags[field.key] || '');
62454     };
62455
62456
62457     textarea.focus = function() {
62458         input.node().focus();
62459     };
62460
62461
62462     return utilRebind(textarea, dispatch$$1, 'on');
62463 }
62464
62465 function uiFieldWikipedia(field, context) {
62466     var dispatch$$1 = dispatch('change'),
62467         wikipedia = services.wikipedia,
62468         wikidata = services.wikidata,
62469         link = select(null),
62470         lang = select(null),
62471         title = select(null),
62472         entity;
62473
62474
62475     function wiki(selection$$1) {
62476         var langcombo = d3combobox()
62477             .fetcher(function(value, cb) {
62478                 var v = value.toLowerCase();
62479
62480                 cb(dataWikipedia.filter(function(d) {
62481                     return d[0].toLowerCase().indexOf(v) >= 0 ||
62482                         d[1].toLowerCase().indexOf(v) >= 0 ||
62483                         d[2].toLowerCase().indexOf(v) >= 0;
62484                 }).map(function(d) {
62485                     return { value: d[1] };
62486                 }));
62487             });
62488
62489         var titlecombo = d3combobox()
62490             .fetcher(function(value, cb) {
62491                 if (!value) {
62492                     value = context.entity(entity.id).tags.name || '';
62493                 }
62494
62495                 var searchfn = value.length > 7 ? wikipedia.search : wikipedia.suggestions;
62496                 searchfn(language()[2], value, function(query, data$$1) {
62497                     cb(data$$1.map(function(d) {
62498                         return { value: d };
62499                     }));
62500                 });
62501             });
62502
62503
62504         lang = selection$$1.selectAll('input.wiki-lang')
62505             .data([0]);
62506
62507         lang = lang.enter()
62508             .append('input')
62509             .attr('type', 'text')
62510             .attr('class', 'wiki-lang')
62511             .attr('placeholder', t('translate.localized_translation_language'))
62512             .merge(lang);
62513
62514         utilGetSetValue(lang, language()[1]);
62515
62516         lang
62517             .call(langcombo)
62518             .on('blur', changeLang)
62519             .on('change', changeLang);
62520
62521
62522         title = selection$$1.selectAll('input.wiki-title')
62523             .data([0]);
62524
62525         title = title.enter()
62526             .append('input')
62527             .attr('type', 'text')
62528             .attr('class', 'wiki-title')
62529             .attr('id', 'preset-input-' + field.id)
62530             .merge(title);
62531
62532         title
62533             .call(titlecombo)
62534             .on('blur', blur)
62535             .on('change', change);
62536
62537
62538         link = selection$$1.selectAll('a.wiki-link')
62539             .data([0]);
62540
62541         link = link.enter()
62542             .append('a')
62543             .attr('class', 'wiki-link button-input-action minor')
62544             .attr('tabindex', -1)
62545             .attr('target', '_blank')
62546             .call(svgIcon('#icon-out-link', 'inline'))
62547             .merge(link);
62548     }
62549
62550
62551     function language() {
62552         var value = utilGetSetValue(lang).toLowerCase();
62553         var locale = utilDetect().locale.toLowerCase();
62554         var localeLanguage;
62555         return lodash.find(dataWikipedia, function(d) {
62556             if (d[2] === locale) localeLanguage = d;
62557             return d[0].toLowerCase() === value ||
62558                 d[1].toLowerCase() === value ||
62559                 d[2] === value;
62560         }) || localeLanguage || ['English', 'English', 'en'];
62561     }
62562
62563
62564     function changeLang() {
62565         utilGetSetValue(lang, language()[1]);
62566         change(true);
62567     }
62568
62569
62570     function blur() {
62571         change(true);
62572     }
62573
62574
62575     function change(skipWikidata) {
62576         var value = utilGetSetValue(title),
62577             m = value.match(/https?:\/\/([-a-z]+)\.wikipedia\.org\/(?:wiki|\1-[-a-z]+)\/([^#]+)(?:#(.+))?/),
62578             l = m && lodash.find(dataWikipedia, function(d) { return m[1] === d[2]; }),
62579             anchor,
62580             syncTags = {};
62581
62582         if (l) {
62583             // Normalize title http://www.mediawiki.org/wiki/API:Query#Title_normalization
62584             value = decodeURIComponent(m[2]).replace(/_/g, ' ');
62585             if (m[3]) {
62586                 try {
62587                     // Best-effort `anchordecode:` implementation
62588                     anchor = decodeURIComponent(m[3].replace(/\.([0-9A-F]{2})/g, '%$1'));
62589                 } catch (e) {
62590                     anchor = decodeURIComponent(m[3]);
62591                 }
62592                 value += '#' + anchor.replace(/_/g, ' ');
62593             }
62594             value = value.slice(0, 1).toUpperCase() + value.slice(1);
62595             utilGetSetValue(lang, l[1]);
62596             utilGetSetValue(title, value);
62597         }
62598
62599         syncTags.wikipedia = value ? language()[2] + ':' + value : undefined;
62600         if (!skipWikidata) {
62601             syncTags.wikidata = undefined;
62602         }
62603
62604         dispatch$$1.call('change', this, syncTags);
62605
62606
62607         if (skipWikidata || !value || !language()[2]) return;
62608
62609         // attempt asynchronous update of wikidata tag..
62610         var initEntityId = entity.id,
62611             initWikipedia = context.entity(initEntityId).tags.wikipedia;
62612
62613         wikidata.itemsByTitle(language()[2], value, function(title, data$$1) {
62614             if (!data$$1 || !Object.keys(data$$1).length) return;
62615             var qids = Object.keys(data$$1);
62616
62617             // 1. most recent change was a tag change
62618             var annotation = t('operations.change_tags.annotation'),
62619                 currAnnotation = context.history().undoAnnotation();
62620             if (currAnnotation !== annotation) return;
62621
62622             // 2. same entity exists and still selected
62623             var selectedIds = context.selectedIDs(),
62624                 currEntityId = selectedIds.length > 0 && selectedIds[0];
62625             if (currEntityId !== initEntityId) return;
62626
62627             // 3. wikipedia value has not changed
62628             var currTags = lodash.clone(context.entity(currEntityId).tags);
62629             if (initWikipedia !== currTags.wikipedia) return;
62630
62631             // ok to coalesce the update of wikidata tag into the previous tag change
62632             currTags.wikidata = qids && lodash.find(qids, function(id) {
62633                 return id.match(/^Q\d+$/);
62634             });
62635
62636             context.overwrite(actionChangeTags(currEntityId, currTags), annotation);
62637             dispatch$$1.call('change', this, currTags);
62638         });
62639     }
62640
62641
62642     wiki.tags = function(tags) {
62643         var value = tags[field.key] || '',
62644             m = value.match(/([^:]+):([^#]+)(?:#(.+))?/),
62645             l = m && lodash.find(dataWikipedia, function(d) { return m[1] === d[2]; }),
62646             anchor = m && m[3];
62647
62648         // value in correct format
62649         if (l) {
62650             utilGetSetValue(lang, l[1]);
62651             utilGetSetValue(title, m[2] + (anchor ? ('#' + anchor) : ''));
62652             if (anchor) {
62653                 try {
62654                     // Best-effort `anchorencode:` implementation
62655                     anchor = encodeURIComponent(anchor.replace(/ /g, '_')).replace(/%/g, '.');
62656                 } catch (e) {
62657                     anchor = anchor.replace(/ /g, '_');
62658                 }
62659             }
62660             link.attr('href', 'https://' + m[1] + '.wikipedia.org/wiki/' +
62661                 m[2].replace(/ /g, '_') + (anchor ? ('#' + anchor) : ''));
62662
62663         // unrecognized value format
62664         } else {
62665             utilGetSetValue(title, value);
62666             if (value && value !== '') {
62667                 utilGetSetValue(lang, '');
62668             }
62669             link.attr('href', 'https://en.wikipedia.org/wiki/Special:Search?search=' + value);
62670         }
62671     };
62672
62673
62674     wiki.entity = function(_) {
62675         if (!arguments.length) return entity;
62676         entity = _;
62677         return wiki;
62678     };
62679
62680
62681     wiki.focus = function() {
62682         title.node().focus();
62683     };
62684
62685
62686     return utilRebind(wiki, dispatch$$1, 'on');
62687 }
62688
62689 var uiFields = {
62690     access: uiFieldAccess,
62691     address: uiFieldAddress,
62692     check: uiFieldCheck,
62693     defaultcheck: uiFieldCheck,
62694     combo: uiFieldCombo,
62695     typeCombo: uiFieldCombo,
62696     multiCombo: uiFieldCombo,
62697     networkCombo: uiFieldCombo,
62698     cycleway: uiFieldCycleway,
62699     text: uiFieldText,
62700     url: uiFieldText,
62701     number: uiFieldText,
62702     email: uiFieldText,
62703     tel: uiFieldText,
62704     localized: uiFieldLocalized,
62705     lanes: uiFieldLanes,
62706     maxspeed: uiFieldMaxspeed,
62707     radio: uiFieldRadio,
62708     restrictions: uiFieldRestrictions,
62709     textarea: uiFieldTextarea,
62710     wikipedia: uiFieldWikipedia
62711 };
62712
62713 function uiPreset(context) {
62714     var dispatch$$1 = dispatch('change'),
62715         state,
62716         fieldsArr,
62717         preset,
62718         tags,
62719         id;
62720
62721
62722     // Field Constructor
62723     function UIField(field, entity, show) {
62724         field = lodash.clone(field);
62725
62726         field.input = uiFields[field.type](field, context)
62727             .on('change', function(t$$1, onInput) {
62728                 dispatch$$1.call('change', field, t$$1, onInput);
62729             });
62730
62731         if (field.input.entity) field.input.entity(entity);
62732
62733         field.keys = field.keys || [field.key];
62734
62735         field.show = show;
62736
62737         field.shown = function() {
62738             return field.id === 'name' || field.show || lodash.some(field.keys, function(key) { return !!tags[key]; });
62739         };
62740
62741         field.modified = function() {
62742             var original = context.graph().base().entities[entity.id];
62743             return lodash.some(field.keys, function(key) {
62744                 return original ? tags[key] !== original.tags[key] : tags[key];
62745             });
62746         };
62747
62748         field.revert = function() {
62749             var original = context.graph().base().entities[entity.id],
62750                 t$$1 = {};
62751             field.keys.forEach(function(key) {
62752                 t$$1[key] = original ? original.tags[key] : undefined;
62753             });
62754             return t$$1;
62755         };
62756
62757         field.present = function() {
62758             return lodash.some(field.keys, function(key) {
62759                 return tags[key];
62760             });
62761         };
62762
62763         field.remove = function() {
62764             var t$$1 = {};
62765             field.keys.forEach(function(key) {
62766                 t$$1[key] = undefined;
62767             });
62768             return t$$1;
62769         };
62770
62771         return field;
62772     }
62773
62774
62775     function fieldKey(field) {
62776         return field.id;
62777     }
62778
62779
62780     function presets(selection$$1) {
62781         selection$$1.call(uiDisclosure()
62782             .title(t('inspector.all_fields'))
62783             .expanded(context.storage('preset_fields.expanded') !== 'false')
62784             .on('toggled', toggled)
62785             .content(content)
62786         );
62787
62788         function toggled(expanded) {
62789             context.storage('preset_fields.expanded', expanded);
62790         }
62791     }
62792
62793
62794     function content(selection$$1) {
62795         if (!fieldsArr) {
62796             var entity = context.entity(id),
62797                 geometry = context.geometry(id),
62798                 presets = context.presets();
62799
62800             fieldsArr = [];
62801
62802             if (presets.field('name')) {
62803                 fieldsArr.push(UIField(presets.field('name'), entity));
62804             }
62805
62806             preset.fields.forEach(function(field) {
62807                 if (field.matchGeometry(geometry)) {
62808                     fieldsArr.push(UIField(field, entity, true));
62809                 }
62810             });
62811
62812             if (entity.isHighwayIntersection(context.graph()) && presets.field('restrictions')) {
62813                 fieldsArr.push(UIField(presets.field('restrictions'), entity, true));
62814             }
62815
62816             presets.universal().forEach(function(field) {
62817                 if (preset.fields.indexOf(field) < 0) {
62818                     fieldsArr.push(UIField(field, entity));
62819                 }
62820             });
62821         }
62822
62823         var shown = fieldsArr.filter(function(field) { return field.shown(); }),
62824             notShown = fieldsArr.filter(function(field) { return !field.shown(); });
62825
62826
62827         var form = selection$$1.selectAll('.preset-form')
62828             .data([0]);
62829
62830         form = form.enter()
62831             .append('div')
62832             .attr('class', 'preset-form inspector-inner fillL3')
62833             .merge(form);
62834
62835
62836         var fields = form.selectAll('.form-field')
62837             .data(shown, fieldKey);
62838
62839         fields.exit()
62840             .remove();
62841
62842         // Enter
62843         var enter = fields.enter()
62844             .append('div')
62845             .attr('class', function(field) {
62846                 return 'form-field form-field-' + field.id;
62847             });
62848
62849         var label = enter
62850             .append('label')
62851             .attr('class', 'form-label')
62852             .attr('for', function(field) { return 'preset-input-' + field.id; })
62853             .text(function(field) { return field.label(); });
62854
62855         var wrap = label
62856             .append('div')
62857             .attr('class', 'form-label-button-wrap');
62858
62859         wrap.append('button')
62860             .attr('class', 'remove-icon')
62861             .attr('tabindex', -1)
62862             .call(svgIcon('#operation-delete'));
62863
62864         wrap.append('button')
62865             .attr('class', 'modified-icon')
62866             .attr('tabindex', -1)
62867             .call(
62868                 (textDirection === 'rtl') ? svgIcon('#icon-redo') : svgIcon('#icon-undo')
62869             );
62870
62871
62872         // Update
62873         fields = fields
62874             .merge(enter);
62875
62876         fields.selectAll('.form-label-button-wrap .remove-icon')
62877             .on('click', remove);
62878
62879         fields.selectAll('.modified-icon')
62880             .on('click', revert);
62881
62882         fields
62883             .order()
62884             .classed('modified', function(field) { return field.modified(); })
62885             .classed('present', function(field) { return field.present(); })
62886             .each(function(field) {
62887                 var reference = uiTagReference(field.reference || { key: field.key }, context);
62888
62889                 if (state === 'hover') {
62890                     reference.showing(false);
62891                 }
62892
62893                 select(this)
62894                     .call(field.input)
62895                     .selectAll('input')
62896                     .on('keydown', function() {
62897                         // if user presses enter, and combobox is not active, accept edits..
62898                         if (event.keyCode === 13 && select('.combobox').empty()) {
62899                             context.enter(modeBrowse$$1(context));
62900                         }
62901                     })
62902                     .call(reference.body)
62903                     .select('.form-label-button-wrap')
62904                     .call(reference.button);
62905
62906                 field.input.tags(tags);
62907             });
62908
62909         notShown = notShown.map(function(field) {
62910             return {
62911                 title: field.label(),
62912                 value: field.label(),
62913                 field: field
62914             };
62915         });
62916
62917
62918         var more = selection$$1.selectAll('.more-fields')
62919             .data((notShown.length > 0) ? [0] : []);
62920
62921         more.exit()
62922             .remove();
62923
62924         more = more.enter()
62925             .append('div')
62926             .attr('class', 'more-fields')
62927             .append('label')
62928             .text(t('inspector.add_fields'))
62929             .merge(more);
62930
62931
62932         var input = more.selectAll('.value')
62933             .data([0]);
62934
62935         input.exit()
62936             .remove();
62937
62938         input = input.enter()
62939             .append('input')
62940             .attr('class', 'value')
62941             .attr('type', 'text')
62942             .merge(input);
62943
62944         input
62945             .call(utilGetSetValue, '')
62946             .attr('placeholder', function() {
62947                 var placeholder = [];
62948                 for (var field in notShown) {
62949                     placeholder.push(notShown[field].title);
62950                 }
62951                 return placeholder.slice(0,3).join(', ') + ((placeholder.length > 3) ? '…' : '');
62952             })
62953             .call(d3combobox().data(notShown)
62954                 .minItems(1)
62955                 .on('accept', show));
62956
62957
62958         function show(field) {
62959             field = field.field;
62960             field.show = true;
62961             content(selection$$1);
62962             field.input.focus();
62963         }
62964
62965
62966         function revert(field) {
62967             event.stopPropagation();
62968             event.preventDefault();
62969             dispatch$$1.call('change', field, field.revert());
62970         }
62971
62972
62973         function remove(field) {
62974             event.stopPropagation();
62975             event.preventDefault();
62976             dispatch$$1.call('change', field, field.remove());
62977         }
62978     }
62979
62980
62981     presets.preset = function(_) {
62982         if (!arguments.length) return preset;
62983         if (preset && preset.id === _.id) return presets;
62984         preset = _;
62985         fieldsArr = null;
62986         return presets;
62987     };
62988
62989
62990     presets.state = function(_) {
62991         if (!arguments.length) return state;
62992         state = _;
62993         return presets;
62994     };
62995
62996
62997     presets.tags = function(_) {
62998         if (!arguments.length) return tags;
62999         tags = _;
63000         // Don't reset fieldsArr here.
63001         return presets;
63002     };
63003
63004
63005     presets.entityID = function(_) {
63006         if (!arguments.length) return id;
63007         if (id === _) return presets;
63008         id = _;
63009         fieldsArr = null;
63010         return presets;
63011     };
63012
63013
63014     return utilRebind(presets, dispatch$$1, 'on');
63015 }
63016
63017 function uiEntityEditor(context) {
63018     var dispatch$$1 = dispatch('choose'),
63019         state = 'select',
63020         coalesceChanges = false,
63021         modified = false,
63022         base,
63023         id,
63024         activePreset,
63025         reference;
63026
63027     var presetEditor = uiPreset(context)
63028         .on('change', changeTags);
63029     var rawTagEditor = uiRawTagEditor(context)
63030         .on('change', changeTags);
63031
63032
63033     function entityEditor(selection$$1) {
63034         var entity = context.entity(id),
63035             tags = lodash.clone(entity.tags);
63036
63037         // Header
63038         var header = selection$$1.selectAll('.header')
63039             .data([0]);
63040
63041         // Enter
63042         var enter = header.enter()
63043             .append('div')
63044             .attr('class', 'header fillL cf');
63045
63046         enter
63047             .append('button')
63048             .attr('class', 'fl preset-reset preset-choose')
63049             .append('span')
63050             .html((textDirection === 'rtl') ? '&#9658;' : '&#9668;');
63051
63052         enter
63053             .append('button')
63054             .attr('class', 'fr preset-close')
63055             .on('click', function() { context.enter(modeBrowse$$1(context)); })
63056             .call(svgIcon(modified ? '#icon-apply' : '#icon-close'));
63057
63058         enter
63059             .append('h3')
63060             .text(t('inspector.edit'));
63061
63062         // Update
63063         header = header
63064             .merge(enter);
63065
63066         header.selectAll('.preset-reset')
63067             .on('click', function() { dispatch$$1.call('choose', this, activePreset); });
63068
63069
63070         // Body
63071         var body = selection$$1.selectAll('.inspector-body')
63072             .data([0]);
63073
63074         // Enter
63075         enter = body.enter()
63076             .append('div')
63077             .attr('class', 'inspector-body');
63078
63079         enter
63080             .append('div')
63081             .attr('class', 'preset-list-item inspector-inner')
63082             .append('div')
63083             .attr('class', 'preset-list-button-wrap')
63084             .append('button')
63085             .attr('class', 'preset-list-button preset-reset')
63086             .call(tooltip().title(t('inspector.back_tooltip')).placement('bottom'))
63087             .append('div')
63088             .attr('class', 'label');
63089
63090         enter
63091             .append('div')
63092             .attr('class', 'inspector-border inspector-preset');
63093
63094         enter
63095             .append('div')
63096             .attr('class', 'inspector-border raw-tag-editor inspector-inner');
63097
63098         enter
63099             .append('div')
63100             .attr('class', 'inspector-border raw-member-editor inspector-inner');
63101
63102         enter
63103             .append('div')
63104             .attr('class', 'raw-membership-editor inspector-inner');
63105
63106         // Update
63107         body = body
63108             .merge(enter);
63109
63110         body.selectAll('.preset-list-button-wrap')
63111             .call(reference.button);
63112
63113         body.selectAll('.preset-list-item')
63114             .call(reference.body);
63115
63116         body.selectAll('.preset-reset')
63117             .on('click', function() { dispatch$$1.call('choose', this, activePreset); });
63118
63119         body.select('.preset-list-item button')
63120             .call(uiPresetIcon()
63121                 .geometry(context.geometry(id))
63122                 .preset(activePreset));
63123
63124         body.select('.preset-list-item .label')
63125             .text(activePreset.name());
63126
63127         body.select('.inspector-preset')
63128             .call(presetEditor
63129                 .preset(activePreset)
63130                 .entityID(id)
63131                 .tags(tags)
63132                 .state(state));
63133
63134         body.select('.raw-tag-editor')
63135             .call(rawTagEditor
63136                 .preset(activePreset)
63137                 .entityID(id)
63138                 .tags(tags)
63139                 .state(state));
63140
63141         if (entity.type === 'relation') {
63142             body.select('.raw-member-editor')
63143                 .style('display', 'block')
63144                 .call(uiRawMemberEditor(context)
63145                     .entityID(id));
63146         } else {
63147             body.select('.raw-member-editor')
63148                 .style('display', 'none');
63149         }
63150
63151         body.select('.raw-membership-editor')
63152             .call(uiRawMembershipEditor(context)
63153                 .entityID(id));
63154
63155
63156         context.history()
63157             .on('change.entity-editor', historyChanged);
63158
63159
63160         function historyChanged() {
63161             if (state === 'hide') return;
63162
63163             var entity = context.hasEntity(id),
63164                 graph = context.graph();
63165             if (!entity) return;
63166
63167             entityEditor.preset(context.presets().match(entity, graph));
63168             entityEditor.modified(base !== graph);
63169             entityEditor(selection$$1);
63170         }
63171     }
63172
63173
63174     function clean(o) {
63175
63176         function cleanVal(k, v) {
63177             function keepSpaces(k) {
63178                 var whitelist = ['opening_hours', 'service_times', 'collection_times',
63179                     'operating_times', 'smoking_hours', 'happy_hours'];
63180                 return lodash.some(whitelist, function(s) { return k.indexOf(s) !== -1; });
63181             }
63182
63183             var blacklist = ['description', 'note', 'fixme'];
63184             if (lodash.some(blacklist, function(s) { return k.indexOf(s) !== -1; })) return v;
63185
63186             var cleaned = v.split(';')
63187                 .map(function(s) { return s.trim(); })
63188                 .join(keepSpaces(k) ? '; ' : ';');
63189
63190             // The code below is not intended to validate websites and emails.
63191             // It is only intended to prevent obvious copy-paste errors. (#2323)
63192
63193             // clean website- and email-like tags
63194             if (k.indexOf('website') !== -1 ||
63195                 k.indexOf('email') !== -1 ||
63196                 cleaned.indexOf('http') === 0) {
63197                 cleaned = cleaned
63198                     .replace(/[\u200B-\u200F\uFEFF]/g, '');  // strip LRM and other zero width chars
63199
63200             }
63201
63202             return cleaned;
63203         }
63204
63205         var out = {}, k, v;
63206         for (k in o) {
63207             if (k && (v = o[k]) !== undefined) {
63208                 out[k] = cleanVal(k, v);
63209             }
63210         }
63211         return out;
63212     }
63213
63214
63215     // Tag changes that fire on input can all get coalesced into a single
63216     // history operation when the user leaves the field.  #2342
63217     function changeTags(changed, onInput) {
63218         var entity = context.entity(id),
63219             annotation = t('operations.change_tags.annotation'),
63220             tags = lodash.clone(entity.tags);
63221
63222         lodash.forEach(changed, function(v, k) {
63223             if (v !== undefined || tags.hasOwnProperty(k)) {
63224                 tags[k] = v;
63225             }
63226         });
63227
63228         if (!onInput) {
63229             tags = clean(tags);
63230         }
63231
63232         if (!lodash.isEqual(entity.tags, tags)) {
63233             if (coalesceChanges) {
63234                 context.overwrite(actionChangeTags(id, tags), annotation);
63235             } else {
63236                 context.perform(actionChangeTags(id, tags), annotation);
63237                 coalesceChanges = !!onInput;
63238             }
63239         }
63240     }
63241
63242
63243     entityEditor.modified = function(_) {
63244         if (!arguments.length) return modified;
63245         modified = _;
63246         selectAll('button.preset-close use')
63247             .attr('xlink:href', (modified ? '#icon-apply' : '#icon-close'));
63248     };
63249
63250
63251     entityEditor.state = function(_) {
63252         if (!arguments.length) return state;
63253         state = _;
63254         return entityEditor;
63255     };
63256
63257
63258     entityEditor.entityID = function(_) {
63259         if (!arguments.length) return id;
63260         id = _;
63261         base = context.graph();
63262         entityEditor.preset(context.presets().match(context.entity(id), base));
63263         entityEditor.modified(false);
63264         coalesceChanges = false;
63265         return entityEditor;
63266     };
63267
63268
63269     entityEditor.preset = function(_) {
63270         if (!arguments.length) return activePreset;
63271         if (_ !== activePreset) {
63272             activePreset = _;
63273             reference = uiTagReference(activePreset.reference(context.geometry(id)), context)
63274                 .showing(false);
63275         }
63276         return entityEditor;
63277     };
63278
63279
63280     return utilRebind(entityEditor, dispatch$$1, 'on');
63281 }
63282
63283 function uiPresetList(context) {
63284     var dispatch$$1 = dispatch('choose'),
63285         id,
63286         currentPreset,
63287         autofocus = false;
63288
63289
63290     function presetList(selection$$1) {
63291         var entity = context.entity(id),
63292             geometry = context.geometry(id);
63293
63294         // Treat entities on addr:interpolation lines as points, not vertices (#3241)
63295         if (geometry === 'vertex' && entity.isOnAddressLine(context.graph())) {
63296             geometry = 'point';
63297         }
63298
63299         var presets = context.presets().matchGeometry(geometry);
63300
63301         selection$$1.html('');
63302
63303         var messagewrap = selection$$1
63304             .append('div')
63305             .attr('class', 'header fillL cf');
63306
63307         var message = messagewrap
63308             .append('h3')
63309             .text(t('inspector.choose'));
63310
63311         if (context.entity(id).isUsed(context.graph())) {
63312             messagewrap
63313                 .append('button')
63314                 .attr('class', 'preset-choose')
63315                 .on('click', function() { dispatch$$1.call('choose', this, currentPreset); })
63316                 .append('span')
63317                 .html((textDirection === 'rtl') ? '&#9668;' : '&#9658;');
63318         } else {
63319             messagewrap
63320                 .append('button')
63321                 .attr('class', 'close')
63322                 .on('click', function() {
63323                     context.enter(modeBrowse$$1(context));
63324                 })
63325                 .call(svgIcon('#icon-close'));
63326         }
63327
63328         function keydown() {
63329             // hack to let delete shortcut work when search is autofocused
63330             if (search.property('value').length === 0 &&
63331                 (event.keyCode === d3keybinding.keyCodes['⌫'] ||
63332                  event.keyCode === d3keybinding.keyCodes['⌦'])) {
63333                 event.preventDefault();
63334                 event.stopPropagation();
63335                 operationDelete([id], context)();
63336             } else if (search.property('value').length === 0 &&
63337                 (event.ctrlKey || event.metaKey) &&
63338                 event.keyCode === d3keybinding.keyCodes.z) {
63339                 event.preventDefault();
63340                 event.stopPropagation();
63341                 context.undo();
63342             } else if (!event.ctrlKey && !event.metaKey) {
63343                 select(this).on('keydown', null);
63344             }
63345         }
63346
63347         function keypress() {
63348             // enter
63349             var value = search.property('value');
63350             if (event.keyCode === 13 && value.length) {
63351                 list.selectAll('.preset-list-item:first-child').datum().choose();
63352             }
63353         }
63354
63355         function inputevent() {
63356             var value = search.property('value');
63357             list.classed('filtered', value.length);
63358             if (value.length) {
63359                 var results = presets.search(value, geometry);
63360                 message.text(t('inspector.results', {
63361                     n: results.collection.length,
63362                     search: value
63363                 }));
63364                 list.call(drawList, results);
63365             } else {
63366                 list.call(drawList, context.presets().defaults(geometry, 36));
63367                 message.text(t('inspector.choose'));
63368             }
63369         }
63370
63371         var searchWrap = selection$$1
63372             .append('div')
63373             .attr('class', 'search-header');
63374
63375         var search = searchWrap
63376             .append('input')
63377             .attr('class', 'preset-search-input')
63378             .attr('placeholder', t('inspector.search'))
63379             .attr('type', 'search')
63380             .on('keydown', keydown)
63381             .on('keypress', keypress)
63382             .on('input', inputevent);
63383
63384         searchWrap
63385             .call(svgIcon('#icon-search', 'pre-text'));
63386
63387         if (autofocus) {
63388             search.node().focus();
63389         }
63390
63391         var listWrap = selection$$1
63392             .append('div')
63393             .attr('class', 'inspector-body');
63394
63395         var list = listWrap
63396             .append('div')
63397             .attr('class', 'preset-list fillL cf')
63398             .call(drawList, context.presets().defaults(geometry, 36));
63399     }
63400
63401
63402     function drawList(list, presets) {
63403         var collection = presets.collection.map(function(preset) {
63404             return preset.members ? CategoryItem(preset) : PresetItem(preset);
63405         });
63406
63407         var items = list.selectAll('.preset-list-item')
63408             .data(collection, function(d) { return d.preset.id; });
63409
63410         items.order();
63411
63412         items.exit()
63413             .remove();
63414
63415         items.enter()
63416             .append('div')
63417             .attr('class', function(item) { return 'preset-list-item preset-' + item.preset.id.replace('/', '-'); })
63418             .classed('current', function(item) { return item.preset === currentPreset; })
63419             .each(function(item) { select(this).call(item); })
63420             .style('opacity', 0)
63421             .transition()
63422             .style('opacity', 1);
63423     }
63424
63425
63426     function CategoryItem(preset) {
63427         var box, sublist, shown = false;
63428
63429         function item(selection$$1) {
63430             var wrap = selection$$1.append('div')
63431                 .attr('class', 'preset-list-button-wrap category col12');
63432
63433             wrap.append('button')
63434                 .attr('class', 'preset-list-button')
63435                 .classed('expanded', false)
63436                 .call(uiPresetIcon()
63437                     .geometry(context.geometry(id))
63438                     .preset(preset))
63439                 .on('click', function() {
63440                     var isExpanded = select(this).classed('expanded');
63441                     var triangle = isExpanded ? '▶ ' :  '▼ ';
63442                     select(this).classed('expanded', !isExpanded);
63443                     select(this).selectAll('.label').text(triangle + preset.name());
63444                     item.choose();
63445                 })
63446                 .append('div')
63447                 .attr('class', 'label')
63448                 .text(function() {
63449                   return '▶ ' + preset.name();
63450                 });
63451
63452             box = selection$$1.append('div')
63453                 .attr('class', 'subgrid col12')
63454                 .style('max-height', '0px')
63455                 .style('opacity', 0);
63456
63457             box.append('div')
63458                 .attr('class', 'arrow');
63459
63460             sublist = box.append('div')
63461                 .attr('class', 'preset-list fillL3 cf fl');
63462         }
63463
63464         item.choose = function() {
63465             if (!box || !sublist) return;
63466
63467             if (shown) {
63468                 shown = false;
63469                 box.transition()
63470                     .duration(200)
63471                     .style('opacity', '0')
63472                     .style('max-height', '0px')
63473                     .style('padding-bottom', '0px');
63474             } else {
63475                 shown = true;
63476                 sublist.call(drawList, preset.members);
63477                 box.transition()
63478                     .duration(200)
63479                     .style('opacity', '1')
63480                     .style('max-height', 200 + preset.members.collection.length * 80 + 'px')
63481                     .style('padding-bottom', '20px');
63482             }
63483         };
63484
63485         item.preset = preset;
63486
63487         return item;
63488     }
63489
63490
63491     function PresetItem(preset) {
63492         function item(selection$$1) {
63493             var wrap = selection$$1.append('div')
63494                 .attr('class', 'preset-list-button-wrap col12');
63495
63496             wrap.append('button')
63497                 .attr('class', 'preset-list-button')
63498                 .call(uiPresetIcon()
63499                     .geometry(context.geometry(id))
63500                     .preset(preset))
63501                 .on('click', item.choose)
63502                 .append('div')
63503                 .attr('class', 'label')
63504                 .text(preset.name());
63505
63506             wrap.call(item.reference.button);
63507             selection$$1.call(item.reference.body);
63508         }
63509
63510         item.choose = function() {
63511             context.presets().choose(preset);
63512
63513             context.perform(
63514                 actionChangePreset(id, currentPreset, preset),
63515                 t('operations.change_tags.annotation')
63516             );
63517
63518             dispatch$$1.call('choose', this, preset);
63519         };
63520
63521         item.help = function() {
63522             event.stopPropagation();
63523             item.reference.toggle();
63524         };
63525
63526         item.preset = preset;
63527         item.reference = uiTagReference(preset.reference(context.geometry(id)), context);
63528
63529         return item;
63530     }
63531
63532
63533     presetList.autofocus = function(_) {
63534         if (!arguments.length) return autofocus;
63535         autofocus = _;
63536         return presetList;
63537     };
63538
63539
63540     presetList.entityID = function(_) {
63541         if (!arguments.length) return id;
63542         id = _;
63543         presetList.preset(context.presets().match(context.entity(id), context.graph()));
63544         return presetList;
63545     };
63546
63547
63548     presetList.preset = function(_) {
63549         if (!arguments.length) return currentPreset;
63550         currentPreset = _;
63551         return presetList;
63552     };
63553
63554
63555     return utilRebind(presetList, dispatch$$1, 'on');
63556 }
63557
63558 function uiViewOnOSM(context) {
63559     var id;
63560
63561     function viewOnOSM(selection) {
63562         var entity = context.entity(id);
63563
63564         selection.style('display', entity.isNew() ? 'none' : null);
63565
63566         var link = selection.selectAll('.view-on-osm')
63567             .data([0]);
63568
63569         link.enter()
63570             .append('a')
63571             .attr('class', 'view-on-osm')
63572             .attr('target', '_blank')
63573             .call(svgIcon('#icon-out-link', 'inline'))
63574             .append('span')
63575             .text(t('inspector.view_on_osm'));
63576
63577         link
63578             .attr('href', context.connection().entityURL(entity));
63579     }
63580
63581
63582     viewOnOSM.entityID = function(_) {
63583         if (!arguments.length) return id;
63584         id = _;
63585         return viewOnOSM;
63586     };
63587
63588     return viewOnOSM;
63589 }
63590
63591 function uiInspector(context) {
63592     var presetList = uiPresetList(context),
63593         entityEditor = uiEntityEditor(context),
63594         state = 'select',
63595         entityID,
63596         newFeature = false;
63597
63598
63599     function inspector(selection$$1) {
63600         presetList
63601             .entityID(entityID)
63602             .autofocus(newFeature)
63603             .on('choose', setPreset);
63604
63605         entityEditor
63606             .state(state)
63607             .entityID(entityID)
63608             .on('choose', showList);
63609
63610         var wrap = selection$$1.selectAll('.panewrap')
63611             .data([0]);
63612
63613         var enter = wrap.enter()
63614             .append('div')
63615             .attr('class', 'panewrap');
63616
63617         enter
63618             .append('div')
63619             .attr('class', 'preset-list-pane pane');
63620
63621         enter
63622             .append('div')
63623             .attr('class', 'entity-editor-pane pane');
63624
63625         wrap = wrap.merge(enter);
63626         var presetPane = wrap.selectAll('.preset-list-pane');
63627         var editorPane = wrap.selectAll('.entity-editor-pane');
63628
63629         var graph = context.graph(),
63630             entity = context.entity(entityID),
63631             showEditor = state === 'hover' ||
63632                 entity.isUsed(graph) ||
63633                 entity.isHighwayIntersection(graph);
63634
63635         if (showEditor) {
63636             wrap.style('right', '0%');
63637             editorPane.call(entityEditor);
63638         } else {
63639             wrap.style('right', '-100%');
63640             presetPane.call(presetList);
63641         }
63642
63643         var footer = selection$$1.selectAll('.footer')
63644             .data([0]);
63645
63646         footer = footer.enter()
63647             .append('div')
63648             .attr('class', 'footer')
63649             .merge(footer);
63650
63651         footer
63652             .call(uiViewOnOSM(context).entityID(entityID));
63653
63654
63655         function showList(preset) {
63656             wrap.transition()
63657                 .styleTween('right', function() { return interpolate('0%', '-100%'); });
63658
63659             presetPane
63660                 .call(presetList.preset(preset).autofocus(true));
63661         }
63662
63663
63664         function setPreset(preset) {
63665             wrap.transition()
63666                 .styleTween('right', function() { return interpolate('-100%', '0%'); });
63667
63668             editorPane
63669                 .call(entityEditor.preset(preset));
63670         }
63671     }
63672
63673
63674     inspector.state = function(_) {
63675         if (!arguments.length) return state;
63676         state = _;
63677         entityEditor.state(state);
63678         return inspector;
63679     };
63680
63681
63682     inspector.entityID = function(_) {
63683         if (!arguments.length) return entityID;
63684         entityID = _;
63685         return inspector;
63686     };
63687
63688
63689     inspector.newFeature = function(_) {
63690         if (!arguments.length) return newFeature;
63691         newFeature = _;
63692         return inspector;
63693     };
63694
63695
63696     return inspector;
63697 }
63698
63699 function uiNotice(context) {
63700
63701     return function(selection) {
63702         var div = selection
63703             .append('div')
63704             .attr('class', 'notice');
63705
63706         var button = div
63707             .append('button')
63708             .attr('class', 'zoom-to notice')
63709             .on('click', function() { context.map().zoom(context.minEditableZoom()); });
63710
63711         button
63712             .call(svgIcon('#icon-plus', 'pre-text'))
63713             .append('span')
63714             .attr('class', 'label')
63715             .text(t('zoom_in_edit'));
63716
63717
63718         function disableTooHigh() {
63719             div.style('display', context.editable() ? 'none' : 'block');
63720         }
63721
63722         context.map()
63723             .on('move.notice', lodash.debounce(disableTooHigh, 500));
63724
63725         disableTooHigh();
63726     };
63727 }
63728
63729 function uiSidebar(context) {
63730     var inspector = uiInspector(context),
63731         current;
63732
63733
63734     function sidebar(selection) {
63735         var featureListWrap = selection
63736             .append('div')
63737             .attr('class', 'feature-list-pane')
63738             .call(uiFeatureList(context));
63739
63740         selection
63741             .call(uiNotice(context));
63742
63743         var inspectorWrap = selection
63744             .append('div')
63745             .attr('class', 'inspector-hidden inspector-wrap fr');
63746
63747
63748         function hover(id) {
63749             if (!current && context.hasEntity(id)) {
63750                 featureListWrap
63751                     .classed('inspector-hidden', true);
63752
63753                 inspectorWrap
63754                     .classed('inspector-hidden', false)
63755                     .classed('inspector-hover', true);
63756
63757                 if (inspector.entityID() !== id || inspector.state() !== 'hover') {
63758                     inspector
63759                         .state('hover')
63760                         .entityID(id);
63761
63762                     inspectorWrap
63763                         .call(inspector);
63764                 }
63765
63766             } else if (!current) {
63767                 featureListWrap
63768                     .classed('inspector-hidden', false);
63769                 inspectorWrap
63770                     .classed('inspector-hidden', true);
63771                 inspector
63772                     .state('hide');
63773             }
63774         }
63775
63776
63777         sidebar.hover = lodash.throttle(hover, 200);
63778
63779
63780         sidebar.select = function(id, newFeature) {
63781             if (!current && id) {
63782                 featureListWrap
63783                     .classed('inspector-hidden', true);
63784
63785                 inspectorWrap
63786                     .classed('inspector-hidden', false)
63787                     .classed('inspector-hover', false);
63788
63789                 if (inspector.entityID() !== id || inspector.state() !== 'select') {
63790                     inspector
63791                         .state('select')
63792                         .entityID(id)
63793                         .newFeature(newFeature);
63794
63795                     inspectorWrap
63796                         .call(inspector);
63797                 }
63798
63799             } else if (!current) {
63800                 featureListWrap
63801                     .classed('inspector-hidden', false);
63802                 inspectorWrap
63803                     .classed('inspector-hidden', true);
63804                 inspector
63805                     .state('hide');
63806             }
63807         };
63808
63809
63810         sidebar.show = function(component) {
63811             featureListWrap
63812                 .classed('inspector-hidden', true);
63813             inspectorWrap
63814                 .classed('inspector-hidden', true);
63815
63816             if (current) current.remove();
63817             current = selection
63818                 .append('div')
63819                 .attr('class', 'sidebar-component')
63820                 .call(component);
63821         };
63822
63823
63824         sidebar.hide = function() {
63825             featureListWrap
63826                 .classed('inspector-hidden', false);
63827             inspectorWrap
63828                 .classed('inspector-hidden', true);
63829
63830             if (current) current.remove();
63831             current = null;
63832         };
63833     }
63834
63835
63836     sidebar.hover = function() {};
63837     sidebar.hover.cancel = function() {};
63838     sidebar.select = function() {};
63839     sidebar.show = function() {};
63840     sidebar.hide = function() {};
63841
63842     return sidebar;
63843 }
63844
63845 function uiSpinner(context) {
63846     var connection = context.connection();
63847
63848
63849     return function(selection) {
63850         var img = selection
63851             .append('img')
63852             .attr('src', context.imagePath('loader-black.gif'))
63853             .style('opacity', 0);
63854
63855         connection
63856             .on('loading.spinner', function() {
63857                 img.transition()
63858                     .style('opacity', 1);
63859             });
63860
63861         connection
63862             .on('loaded.spinner', function() {
63863                 img.transition()
63864                     .style('opacity', 0);
63865             });
63866     };
63867 }
63868
63869 function uiSplash(context) {
63870
63871     return function(selection$$1) {
63872         if (context.storage('sawSplash'))
63873              return;
63874
63875         context.storage('sawSplash', true);
63876
63877         var modalSelection = uiModal(selection$$1);
63878
63879         modalSelection.select('.modal')
63880             .attr('class', 'modal-splash modal col6');
63881
63882         var introModal = modalSelection.select('.content')
63883             .append('div')
63884             .attr('class', 'fillL');
63885
63886         introModal
63887             .append('div')
63888             .attr('class','modal-section cf')
63889             .append('h3').text(t('splash.welcome'));
63890
63891         introModal
63892             .append('div')
63893             .attr('class','modal-section')
63894             .append('p')
63895             .html(t('splash.text', {
63896                 version: context.version,
63897                 website: '<a href="http://ideditor.com/">ideditor.com</a>',
63898                 github: '<a href="https://github.com/openstreetmap/iD">github.com</a>'
63899             }));
63900
63901         var buttons = introModal
63902             .append('div')
63903             .attr('class', 'modal-actions cf');
63904
63905         buttons
63906             .append('button')
63907             .attr('class', 'col6 walkthrough')
63908             .text(t('splash.walkthrough'))
63909             .on('click', function() {
63910                 select(document.body).call(uiIntro(context));
63911                 modalSelection.close();
63912             });
63913
63914         buttons
63915             .append('button')
63916             .attr('class', 'col6 start')
63917             .text(t('splash.start'))
63918             .on('click', modalSelection.close);
63919
63920         modalSelection.select('button.close')
63921             .attr('class','hide');
63922
63923     };
63924 }
63925
63926 function uiStatus(context) {
63927     var connection = context.connection();
63928
63929     return function(selection$$1) {
63930
63931         function update() {
63932             connection.status(function(err, apiStatus) {
63933                 selection$$1.html('');
63934
63935                 if (err) {
63936                     if (apiStatus === 'rateLimited') {
63937                         selection$$1
63938                             .text(t('status.rateLimit'))
63939                             .append('a')
63940                             .attr('class', 'api-status-login')
63941                             .attr('target', '_blank')
63942                             .call(svgIcon('#icon-out-link', 'inline'))
63943                             .append('span')
63944                             .text(t('login'))
63945                             .on('click.login', function() {
63946                                 event.preventDefault();
63947                                 connection.authenticate();
63948                             });
63949                     } else {
63950                         // TODO: nice messages for different error types
63951                         selection$$1.text(t('status.error'));
63952                     }
63953
63954                 } else if (apiStatus === 'readonly') {
63955                     selection$$1.text(t('status.readonly'));
63956                 } else if (apiStatus === 'offline') {
63957                     selection$$1.text(t('status.offline'));
63958                 }
63959
63960                 selection$$1.attr('class', 'api-status ' + (err ? 'error' : apiStatus));
63961             });
63962         }
63963
63964         connection
63965             .on('change', function() { update(selection$$1); });
63966
63967         window.setInterval(update, 90000);
63968         update(selection$$1);
63969     };
63970 }
63971
63972 function uiUndoRedo(context) {
63973     var commands = [{
63974         id: 'undo',
63975         cmd: uiCmd('⌘Z'),
63976         action: function() { if (!(context.inIntro() || saving())) context.undo(); },
63977         annotation: function() { return context.history().undoAnnotation(); }
63978     }, {
63979         id: 'redo',
63980         cmd: uiCmd('⌘⇧Z'),
63981         action: function() {if (!(context.inIntro() || saving())) context.redo(); },
63982         annotation: function() { return context.history().redoAnnotation(); }
63983     }];
63984
63985
63986     function saving() {
63987         return context.mode().id === 'save';
63988     }
63989
63990
63991     return function(selection$$1) {
63992         var tooltipBehavior = tooltip()
63993             .placement('bottom')
63994             .html(true)
63995             .title(function (d) {
63996                 return uiTooltipHtml(d.annotation() ?
63997                     t(d.id + '.tooltip', {action: d.annotation()}) :
63998                     t(d.id + '.nothing'), d.cmd);
63999             });
64000
64001         var buttons = selection$$1.selectAll('button')
64002             .data(commands)
64003             .enter()
64004             .append('button')
64005             .attr('class', 'col6 disabled')
64006             .on('click', function(d) { return d.action(); })
64007             .call(tooltipBehavior);
64008
64009         buttons.each(function(d) {
64010             var iconName = d.id;
64011             if (textDirection === 'rtl') {
64012                 if (iconName === 'undo') {
64013                     iconName = 'redo';
64014                 } else if (iconName === 'redo') {
64015                     iconName = 'undo';
64016                 }
64017             }
64018             select(this)
64019                 .call(svgIcon('#icon-' + iconName));
64020         });
64021
64022         var keybinding = d3keybinding('undo')
64023             .on(commands[0].cmd, function() { event.preventDefault(); commands[0].action(); })
64024             .on(commands[1].cmd, function() { event.preventDefault(); commands[1].action(); });
64025
64026         select(document)
64027             .call(keybinding);
64028
64029         context.history()
64030             .on('change.undo_redo', update);
64031
64032         context
64033             .on('enter.undo_redo', update);
64034
64035         function update() {
64036             buttons
64037                 .property('disabled', saving())
64038                 .classed('disabled', function(d) { return !d.annotation(); })
64039                 .each(function() {
64040                     var selection$$1 = select(this);
64041                     if (selection$$1.property('tooltipVisible')) {
64042                         selection$$1.call(tooltipBehavior.show);
64043                     }
64044                 });
64045         }
64046     };
64047 }
64048
64049 function uiZoom(context) {
64050     var zooms = [{
64051         id: 'zoom-in',
64052         icon: 'plus',
64053         title: t('zoom.in'),
64054         action: context.zoomIn,
64055         key: '+'
64056     }, {
64057         id: 'zoom-out',
64058         icon: 'minus',
64059         title: t('zoom.out'),
64060         action: context.zoomOut,
64061         key: '-'
64062     }];
64063
64064
64065     function zoomIn() {
64066         event.preventDefault();
64067         if (!context.inIntro()) context.zoomIn();
64068     }
64069
64070
64071     function zoomOut() {
64072         event.preventDefault();
64073         if (!context.inIntro()) context.zoomOut();
64074     }
64075
64076
64077     function zoomInFurther() {
64078         event.preventDefault();
64079         if (!context.inIntro()) context.zoomInFurther();
64080     }
64081
64082
64083     function zoomOutFurther() {
64084         event.preventDefault();
64085         if (!context.inIntro()) context.zoomOutFurther();
64086     }
64087
64088
64089     return function(selection$$1) {
64090         var button = selection$$1.selectAll('button')
64091             .data(zooms)
64092             .enter()
64093             .append('button')
64094             .attr('tabindex', -1)
64095             .attr('class', function(d) { return d.id; })
64096             .on('click.editor', function(d) { d.action(); })
64097             .call(tooltip()
64098                 .placement((textDirection === 'rtl') ? 'right' : 'left')
64099                 .html(true)
64100                 .title(function(d) {
64101                     return uiTooltipHtml(d.title, d.key);
64102                 })
64103             );
64104
64105         button.each(function(d) {
64106             select(this)
64107                 .call(svgIcon('#icon-' + d.icon, 'light'));
64108         });
64109
64110         var keybinding = d3keybinding('zoom');
64111
64112         lodash.each(['=','ffequals','plus','ffplus'], function(key) {
64113             keybinding.on([key, '⇧' + key], zoomIn);
64114             keybinding.on([uiCmd('⌘' + key), uiCmd('⌘⇧' + key)], zoomInFurther);
64115         });
64116         lodash.each(['-','ffminus','dash'], function(key) {
64117             keybinding.on([key, '⇧' + key], zoomOut);
64118             keybinding.on([uiCmd('⌘' + key), uiCmd('⌘⇧' + key)], zoomOutFurther);
64119         });
64120
64121         select(document)
64122             .call(keybinding);
64123     };
64124 }
64125
64126 function uiInit(context) {
64127
64128     function render(container) {
64129         var map$$1 = context.map();
64130
64131         var hash = behaviorHash(context);
64132         hash();
64133
64134         if (!hash.hadHash) {
64135             map$$1.centerZoom([0, 0], 2);
64136         }
64137
64138         container
64139             .append('svg')
64140             .attr('id', 'defs')
64141             .call(svgDefs(context));
64142
64143         container
64144             .append('div')
64145             .attr('id', 'sidebar')
64146             .attr('class', 'col4')
64147             .call(ui.sidebar);
64148
64149         var content = container
64150             .append('div')
64151             .attr('id', 'content');
64152
64153         var bar = content
64154             .append('div')
64155             .attr('id', 'bar')
64156             .attr('class', 'fillD');
64157
64158         content
64159             .append('div')
64160             .attr('id', 'map')
64161             .attr('dir', 'ltr')
64162             .call(map$$1);
64163
64164         if (textDirection === 'rtl') {
64165             select('body').attr('dir', 'rtl');
64166         }
64167
64168         content
64169             .call(uiMapInMap(context));
64170
64171         content
64172             .append('div')
64173             .call(uiInfo(context));
64174
64175         bar
64176             .append('div')
64177             .attr('class', 'spacer col4');
64178
64179         var limiter = bar.append('div')
64180             .attr('class', 'limiter');
64181
64182         limiter
64183             .append('div')
64184             .attr('class', 'button-wrap joined col3')
64185             .call(uiModes(context), limiter);
64186
64187         limiter
64188             .append('div')
64189             .attr('class', 'button-wrap joined col1')
64190             .call(uiUndoRedo(context));
64191
64192         limiter
64193             .append('div')
64194             .attr('class', 'button-wrap col1')
64195             .call(uiSave(context));
64196
64197         bar
64198             .append('div')
64199             .attr('class', 'full-screen')
64200             .call(uiFullScreen(context));
64201
64202         bar
64203             .append('div')
64204             .attr('class', 'spinner')
64205             .call(uiSpinner(context));
64206
64207         var controls = bar
64208             .append('div')
64209             .attr('class', 'map-controls');
64210
64211         controls
64212             .append('div')
64213             .attr('class', 'map-control zoombuttons')
64214             .call(uiZoom(context));
64215
64216         controls
64217             .append('div')
64218             .attr('class', 'map-control geolocate-control')
64219             .call(uiGeolocate(context));
64220
64221         controls
64222             .append('div')
64223             .attr('class', 'map-control background-control')
64224             .call(uiBackground(context));
64225
64226         controls
64227             .append('div')
64228             .attr('class', 'map-control map-data-control')
64229             .call(uiMapData(context));
64230
64231         controls
64232             .append('div')
64233             .attr('class', 'map-control help-control')
64234             .call(uiHelp(context));
64235
64236         var about = content
64237             .append('div')
64238             .attr('id', 'about');
64239
64240         about
64241             .append('div')
64242             .attr('id', 'attrib')
64243             .attr('dir', 'ltr')
64244             .call(uiAttribution(context));
64245
64246         var footer = about
64247             .append('div')
64248             .attr('id', 'footer')
64249             .attr('class', 'fillD');
64250
64251         footer
64252             .append('div')
64253             .attr('class', 'api-status')
64254             .call(uiStatus(context));
64255
64256         footer
64257             .append('div')
64258             .attr('id', 'scale-block')
64259             .call(uiScale(context));
64260
64261         var aboutList = footer
64262             .append('div')
64263             .attr('id', 'info-block')
64264             .append('ul')
64265             .attr('id', 'about-list');
64266
64267         if (!context.embed()) {
64268             aboutList.call(uiAccount(context));
64269         }
64270
64271         aboutList
64272             .append('li')
64273             .append('a')
64274             .attr('target', '_blank')
64275             .attr('tabindex', -1)
64276             .attr('href', 'https://github.com/openstreetmap/iD')
64277             .text(context.version);
64278
64279         var issueLinks = aboutList
64280             .append('li');
64281
64282         issueLinks
64283             .append('a')
64284             .attr('target', '_blank')
64285             .attr('tabindex', -1)
64286             .attr('href', 'https://github.com/openstreetmap/iD/issues')
64287             .call(svgIcon('#icon-bug', 'light'))
64288             .call(tooltip().title(t('report_a_bug')).placement('top'));
64289
64290         issueLinks
64291             .append('a')
64292             .attr('target', '_blank')
64293             .attr('tabindex', -1)
64294             .attr('href', 'https://github.com/openstreetmap/iD/blob/master/CONTRIBUTING.md#translating')
64295             .call(svgIcon('#icon-translate', 'light'))
64296             .call(tooltip().title(t('help_translate')).placement('top'));
64297
64298         aboutList
64299             .append('li')
64300             .attr('class', 'feature-warning')
64301             .attr('tabindex', -1)
64302             .call(uiFeatureInfo(context));
64303
64304         aboutList
64305             .append('li')
64306             .attr('class', 'user-list')
64307             .attr('tabindex', -1)
64308             .call(uiContributors(context));
64309
64310
64311         window.onbeforeunload = function() {
64312             return context.save();
64313         };
64314
64315         window.onunload = function() {
64316             context.history().unlock();
64317         };
64318
64319         var mapDimensions = map$$1.dimensions();
64320
64321         function onResize() {
64322             mapDimensions = utilGetDimensions(content, true);
64323             map$$1.dimensions(mapDimensions);
64324         }
64325
64326         select(window)
64327             .on('resize.editor', onResize);
64328
64329         onResize();
64330
64331         function pan(d) {
64332             return function() {
64333                 event.preventDefault();
64334                 if (!context.inIntro()) {
64335                     context.pan(d, 100);
64336                 }
64337             };
64338         }
64339
64340         // pan amount
64341         var pa = 10;
64342
64343         var keybinding = d3keybinding('main')
64344             .on('⌫', function() { event.preventDefault(); })
64345             .on('←', pan([pa, 0]))
64346             .on('↑', pan([0, pa]))
64347             .on('→', pan([-pa, 0]))
64348             .on('↓', pan([0, -pa]))
64349             .on(['⇧←', uiCmd('⌘←')], pan([mapDimensions[0], 0]))
64350             .on(['⇧↑', uiCmd('⌘↑')], pan([0, mapDimensions[1]]))
64351             .on(['⇧→', uiCmd('⌘→')], pan([-mapDimensions[0], 0]))
64352             .on(['⇧↓', uiCmd('⌘↓')], pan([0, -mapDimensions[1]]));
64353
64354         select(document)
64355             .call(keybinding);
64356
64357         context.enter(modeBrowse$$1(context));
64358
64359         context.container()
64360             .call(uiSplash(context))
64361             .call(uiRestore(context));
64362
64363         var authenticating = uiLoading(context)
64364             .message(t('loading_auth'))
64365             .blocking(true);
64366
64367         context.connection()
64368             .on('authLoading.ui', function() {
64369                 context.container()
64370                     .call(authenticating);
64371             })
64372             .on('authDone.ui', function() {
64373                 authenticating.close();
64374             });
64375     }
64376
64377
64378     function ui(node, callback) {
64379         var container = select(node);
64380         context.container(container);
64381         context.loadLocale(function(err) {
64382             if (!err) {
64383                 render(container);
64384             }
64385             if (callback) {
64386                 callback(err);
64387             }
64388         });
64389     }
64390
64391     ui.sidebar = uiSidebar(context);
64392
64393     return ui;
64394 }
64395
64396 function uiCommit(context) {
64397     var dispatch$$1 = dispatch('cancel', 'save');
64398
64399
64400     function commit(selection$$1) {
64401         var changes = context.history().changes(),
64402             summary = context.history().difference().summary();
64403
64404         selection$$1
64405             .append('div')
64406             .attr('class', 'header fillL')
64407             .append('h3')
64408             .text(t('commit.title'));
64409
64410         var body = selection$$1
64411             .append('div')
64412             .attr('class', 'body');
64413
64414         var commentSection = body
64415             .append('div')
64416             .attr('class', 'modal-section form-field commit-form');
64417
64418         commentSection
64419             .append('label')
64420             .attr('class', 'form-label')
64421             .text(t('commit.message_label'));
64422
64423         var commentField = commentSection
64424             .append('textarea')
64425             .attr('placeholder', t('commit.description_placeholder'))
64426             .attr('maxlength', 255)
64427             .property('value', context.storage('comment') || '')
64428             .on('input.save', checkComment)
64429             .on('change.save', checkComment)
64430             .on('blur.save', function() {
64431                 context.storage('comment', this.value);
64432             });
64433
64434
64435         commentField.node().select();
64436
64437         context.connection().userChangesets(function (err, changesets) {
64438             if (err) return;
64439
64440             var comments = [];
64441
64442             for (var i = 0; i < changesets.length; i++) {
64443                 if (changesets[i].tags.comment) {
64444                     comments.push({
64445                         title: changesets[i].tags.comment,
64446                         value: changesets[i].tags.comment
64447                     });
64448                 }
64449             }
64450
64451             commentField
64452                 .call(d3combobox().caseSensitive(true).data(comments));
64453         });
64454
64455         var clippyArea = commentSection.append('div')
64456             .attr('class', 'clippy-area');
64457
64458         var changeSetInfo = commentSection.append('div')
64459             .attr('class', 'changeset-info');
64460
64461         changeSetInfo.append('a')
64462             .attr('target', '_blank')
64463             .attr('tabindex', -1)
64464             .call(svgIcon('#icon-out-link', 'inline'))
64465             .attr('href', t('commit.about_changeset_comments_link'))
64466             .append('span')
64467             .text(t('commit.about_changeset_comments'));
64468
64469
64470         // Warnings
64471         var warnings = body.selectAll('div.warning-section')
64472             .data([context.history().validate(changes)]);
64473
64474         warnings = warnings.enter()
64475             .append('div')
64476             .attr('class', 'modal-section warning-section fillL2')
64477             .style('display', function(d) { return lodash.isEmpty(d) ? 'none' : null; })
64478             .style('background', '#ffb')
64479             .merge(warnings);
64480
64481         warnings
64482             .append('h3')
64483             .text(t('commit.warnings'));
64484
64485         warnings
64486             .append('ul')
64487             .attr('class', 'changeset-list');
64488
64489         var warningLi = warnings.select('ul').selectAll('li')
64490             .data(function(d) { return d; });
64491
64492         warningLi = warningLi.enter()
64493             .append('li')
64494             .on('mouseover', mouseover)
64495             .on('mouseout', mouseout)
64496             .on('click', warningClick)
64497             .merge(warningLi);
64498
64499         warningLi
64500             .call(svgIcon('#icon-alert', 'pre-text'));
64501
64502         warningLi
64503             .append('strong')
64504             .text(function(d) { return d.message; });
64505
64506         warningLi.filter(function(d) { return d.tooltip; })
64507             .call(tooltip()
64508                 .title(function(d) { return d.tooltip; })
64509                 .placement('top')
64510             );
64511
64512
64513         // Upload Explanation
64514         var saveSection = body
64515             .append('div')
64516             .attr('class','modal-section save-section fillL cf');
64517
64518         var prose = saveSection
64519             .append('p')
64520             .attr('class', 'commit-info')
64521             .html(t('commit.upload_explanation'));
64522
64523
64524         context.connection().userDetails(function(err, user) {
64525             if (err) return;
64526
64527             var userLink = select(document.createElement('div'));
64528
64529             if (user.image_url) {
64530                 userLink
64531                     .append('img')
64532                     .attr('src', user.image_url)
64533                     .attr('class', 'icon pre-text user-icon');
64534             }
64535
64536             userLink
64537                 .append('a')
64538                 .attr('class','user-info')
64539                 .text(user.display_name)
64540                 .attr('href', context.connection().userURL(user.display_name))
64541                 .attr('tabindex', -1)
64542                 .attr('target', '_blank');
64543
64544             prose
64545                 .html(t('commit.upload_explanation_with_user', { user: userLink.html() }));
64546         });
64547
64548
64549         // Buttons
64550         var buttonSection = saveSection
64551             .append('div')
64552             .attr('class','buttons fillL cf');
64553
64554         var cancelButton = buttonSection
64555             .append('button')
64556             .attr('class', 'secondary-action col5 button cancel-button')
64557             .on('click.cancel', function() { dispatch$$1.call('cancel'); });
64558
64559         cancelButton
64560             .append('span')
64561             .attr('class', 'label')
64562             .text(t('commit.cancel'));
64563
64564         var saveButton = buttonSection
64565             .append('button')
64566             .attr('class', 'action col5 button save-button')
64567             .attr('disabled', function() {
64568                 var n = select('.commit-form textarea').node();
64569                 return (n && n.value.length) ? null : true;
64570             })
64571             .on('click.save', function() {
64572                 dispatch$$1.call('save', this, {
64573                     comment: commentField.node().value
64574                 });
64575             });
64576
64577         saveButton
64578             .append('span')
64579             .attr('class', 'label')
64580             .text(t('commit.save'));
64581
64582
64583         // Changes
64584         var changeSection = body
64585             .append('div')
64586             .attr('class', 'commit-section modal-section fillL2');
64587
64588         changeSection.append('h3')
64589             .text(t('commit.changes', { count: summary.length }));
64590
64591         var li = changeSection
64592             .append('ul')
64593             .attr('class', 'changeset-list')
64594             .selectAll('li')
64595             .data(summary);
64596
64597         li = li.enter()
64598             .append('li')
64599             .on('mouseover', mouseover)
64600             .on('mouseout', mouseout)
64601             .on('click', zoomToEntity)
64602             .merge(li);
64603
64604         li.each(function(d) {
64605             select(this)
64606                 .call(svgIcon('#icon-' + d.entity.geometry(d.graph), 'pre-text ' + d.changeType));
64607         });
64608
64609         li.append('span')
64610             .attr('class', 'change-type')
64611             .text(function(d) { return t('commit.' + d.changeType) + ' '; });
64612
64613         li.append('strong')
64614             .attr('class', 'entity-type')
64615             .text(function(d) {
64616                 var matched = context.presets().match(d.entity, d.graph);
64617                 return (matched && matched.name()) || utilDisplayType(d.entity.id);
64618             });
64619
64620         li.append('span')
64621             .attr('class', 'entity-name')
64622             .text(function(d) {
64623                 var name = utilDisplayName(d.entity) || '',
64624                     string = '';
64625                 if (name !== '') string += ':';
64626                 return string += ' ' + name;
64627             });
64628
64629         li.style('opacity', 0)
64630             .transition()
64631             .style('opacity', 1);
64632
64633
64634         // Call checkComment off the bat, in case a changeset
64635         // comment is recovered from localStorage
64636         utilTriggerEvent(commentField, 'input');
64637
64638
64639         function mouseover(d) {
64640             if (d.entity) {
64641                 context.surface().selectAll(
64642                     utilEntityOrMemberSelector([d.entity.id], context.graph())
64643                 ).classed('hover', true);
64644             }
64645         }
64646
64647
64648         function mouseout() {
64649             context.surface().selectAll('.hover')
64650                 .classed('hover', false);
64651         }
64652
64653
64654         function warningClick(d) {
64655             if (d.entity) {
64656                 context.map().zoomTo(d.entity);
64657                 context.enter(
64658                     modeSelect(context, [d.entity.id]).suppressMenu(true)
64659                 );
64660             }
64661         }
64662
64663
64664         function zoomToEntity(change) {
64665             var entity = change.entity;
64666             if (change.changeType !== 'deleted' &&
64667                 context.graph().entity(entity.id).geometry(context.graph()) !== 'vertex') {
64668                 context.map().zoomTo(entity);
64669                 context.surface().selectAll(
64670                     utilEntityOrMemberSelector([entity.id], context.graph()))
64671                     .classed('hover', true);
64672             }
64673         }
64674
64675
64676         function checkComment() {
64677             selectAll('.save-section .save-button')
64678                 .attr('disabled', (this.value.length ? null : true));
64679
64680             var googleWarning = clippyArea
64681                .html('')
64682                .selectAll('a')
64683                .data(this.value.match(/google/i) ? [true] : []);
64684
64685             googleWarning.exit()
64686                 .remove();
64687
64688             googleWarning.enter()
64689                .append('a')
64690                .attr('target', '_blank')
64691                .attr('tabindex', -1)
64692                .call(svgIcon('#icon-alert', 'inline'))
64693                .attr('href', t('commit.google_warning_link'))
64694                .append('span')
64695                .text(t('commit.google_warning'));
64696         }
64697     }
64698
64699     return utilRebind(commit, dispatch$$1, 'on');
64700 }
64701
64702 function uiConfirm(selection) {
64703     var modalSelection = uiModal(selection);
64704
64705     modalSelection.select('.modal')
64706         .classed('modal-alert', true);
64707
64708     var section = modalSelection.select('.content');
64709
64710     section.append('div')
64711         .attr('class', 'modal-section header');
64712
64713     section.append('div')
64714         .attr('class', 'modal-section message-text');
64715
64716     var buttons = section.append('div')
64717         .attr('class', 'modal-section buttons cf');
64718
64719
64720     modalSelection.okButton = function() {
64721         buttons
64722             .append('button')
64723             .attr('class', 'action col4')
64724             .on('click.confirm', function() {
64725                 modalSelection.remove();
64726             })
64727             .text(t('confirm.okay'));
64728
64729         return modalSelection;
64730     };
64731
64732
64733     return modalSelection;
64734 }
64735
64736 function uiConflicts(context) {
64737     var dispatch$$1 = dispatch('download', 'cancel', 'save'),
64738         list;
64739
64740
64741     function conflicts(selection$$1) {
64742         var header = selection$$1
64743             .append('div')
64744             .attr('class', 'header fillL');
64745
64746         header
64747             .append('button')
64748             .attr('class', 'fr')
64749             .on('click', function() { dispatch$$1.call('cancel'); })
64750             .call(svgIcon('#icon-close'));
64751
64752         header
64753             .append('h3')
64754             .text(t('save.conflict.header'));
64755
64756         var body = selection$$1
64757             .append('div')
64758             .attr('class', 'body fillL');
64759
64760         body
64761             .append('div')
64762             .attr('class', 'conflicts-help')
64763             .text(t('save.conflict.help'))
64764             .append('a')
64765             .attr('class', 'conflicts-download')
64766             .text(t('save.conflict.download_changes'))
64767             .on('click.download', function() { dispatch$$1.call('download'); });
64768
64769         body
64770             .append('div')
64771             .attr('class', 'conflict-container fillL3')
64772             .call(showConflict, 0);
64773
64774         body
64775             .append('div')
64776             .attr('class', 'conflicts-done')
64777             .attr('opacity', 0)
64778             .style('display', 'none')
64779             .text(t('save.conflict.done'));
64780
64781         var buttons = body
64782             .append('div')
64783             .attr('class','buttons col12 joined conflicts-buttons');
64784
64785         buttons
64786             .append('button')
64787             .attr('disabled', list.length > 1)
64788             .attr('class', 'action conflicts-button col6')
64789             .text(t('save.title'))
64790             .on('click.try_again', function() { dispatch$$1.call('save'); });
64791
64792         buttons
64793             .append('button')
64794             .attr('class', 'secondary-action conflicts-button col6')
64795             .text(t('confirm.cancel'))
64796             .on('click.cancel', function() { dispatch$$1.call('cancel'); });
64797     }
64798
64799
64800     function showConflict(selection$$1, index) {
64801         if (index < 0 || index >= list.length) return;
64802
64803         var parent = select(selection$$1.node().parentNode);
64804
64805         // enable save button if this is the last conflict being reviewed..
64806         if (index === list.length - 1) {
64807             window.setTimeout(function() {
64808                 parent.select('.conflicts-button')
64809                     .attr('disabled', null);
64810
64811                 parent.select('.conflicts-done')
64812                     .transition()
64813                     .attr('opacity', 1)
64814                     .style('display', 'block');
64815             }, 250);
64816         }
64817
64818         var item = selection$$1
64819             .selectAll('.conflict')
64820             .data([list[index]]);
64821
64822         var enter = item.enter()
64823             .append('div')
64824             .attr('class', 'conflict');
64825
64826         enter
64827             .append('h4')
64828             .attr('class', 'conflict-count')
64829             .text(t('save.conflict.count', { num: index + 1, total: list.length }));
64830
64831         enter
64832             .append('a')
64833             .attr('class', 'conflict-description')
64834             .attr('href', '#')
64835             .text(function(d) { return d.name; })
64836             .on('click', function(d) {
64837                 zoomToEntity(d.id);
64838                 event.preventDefault();
64839             });
64840
64841         var details = enter
64842             .append('div')
64843             .attr('class', 'conflict-detail-container');
64844
64845         details
64846             .append('ul')
64847             .attr('class', 'conflict-detail-list')
64848             .selectAll('li')
64849             .data(function(d) { return d.details || []; })
64850             .enter()
64851             .append('li')
64852             .attr('class', 'conflict-detail-item')
64853             .html(function(d) { return d; });
64854
64855         details
64856             .append('div')
64857             .attr('class', 'conflict-choices')
64858             .call(addChoices);
64859
64860         details
64861             .append('div')
64862             .attr('class', 'conflict-nav-buttons joined cf')
64863             .selectAll('button')
64864             .data(['previous', 'next'])
64865             .enter()
64866             .append('button')
64867             .text(function(d) { return t('save.conflict.' + d); })
64868             .attr('class', 'conflict-nav-button action col6')
64869             .attr('disabled', function(d, i) {
64870                 return (i === 0 && index === 0) ||
64871                     (i === 1 && index === list.length - 1) || null;
64872             })
64873             .on('click', function(d, i) {
64874                 var container = parent.select('.conflict-container'),
64875                 sign = (i === 0 ? -1 : 1);
64876
64877                 container
64878                     .selectAll('.conflict')
64879                     .remove();
64880
64881                 container
64882                     .call(showConflict, index + sign);
64883
64884                 event.preventDefault();
64885             });
64886
64887         item.exit()
64888             .remove();
64889     }
64890
64891
64892     function addChoices(selection$$1) {
64893         var choices = selection$$1
64894             .append('ul')
64895             .attr('class', 'layer-list')
64896             .selectAll('li')
64897             .data(function(d) { return d.choices || []; });
64898
64899         var enter = choices.enter()
64900             .append('li')
64901             .attr('class', 'layer');
64902
64903         var label = enter
64904             .append('label');
64905
64906         label
64907             .append('input')
64908             .attr('type', 'radio')
64909             .attr('name', function(d) { return d.id; })
64910             .on('change', function(d, i) {
64911                 var ul = this.parentNode.parentNode.parentNode;
64912                 ul.__data__.chosen = i;
64913                 choose(ul, d);
64914             });
64915
64916         label
64917             .append('span')
64918             .text(function(d) { return d.text; });
64919
64920         choices
64921             .each(function(d, i) {
64922                 var ul = this.parentNode;
64923                 if (ul.__data__.chosen === i) choose(ul, d);
64924             });
64925     }
64926
64927
64928     function choose(ul, datum) {
64929         if (event) event.preventDefault();
64930
64931         select(ul)
64932             .selectAll('li')
64933             .classed('active', function(d) { return d === datum; })
64934             .selectAll('input')
64935             .property('checked', function(d) { return d === datum; });
64936
64937         var extent$$1 = geoExtent$$1(),
64938             entity;
64939
64940         entity = context.graph().hasEntity(datum.id);
64941         if (entity) extent$$1._extend(entity.extent(context.graph()));
64942
64943         datum.action();
64944
64945         entity = context.graph().hasEntity(datum.id);
64946         if (entity) extent$$1._extend(entity.extent(context.graph()));
64947
64948         zoomToEntity(datum.id, extent$$1);
64949     }
64950
64951
64952     function zoomToEntity(id, extent$$1) {
64953         context.surface().selectAll('.hover')
64954             .classed('hover', false);
64955
64956         var entity = context.graph().hasEntity(id);
64957         if (entity) {
64958             if (extent$$1) {
64959                 context.map().trimmedExtent(extent$$1);
64960             } else {
64961                 context.map().zoomTo(entity);
64962             }
64963             context.surface().selectAll(
64964                 utilEntityOrMemberSelector([entity.id], context.graph()))
64965                 .classed('hover', true);
64966         }
64967     }
64968
64969
64970     // The conflict list should be an array of objects like:
64971     // {
64972     //     id: id,
64973     //     name: entityName(local),
64974     //     details: merge.conflicts(),
64975     //     chosen: 1,
64976     //     choices: [
64977     //         choice(id, keepMine, forceLocal),
64978     //         choice(id, keepTheirs, forceRemote)
64979     //     ]
64980     // }
64981     conflicts.list = function(_) {
64982         if (!arguments.length) return list;
64983         list = _;
64984         return conflicts;
64985     };
64986
64987
64988     return utilRebind(conflicts, dispatch$$1, 'on');
64989 }
64990
64991 function uiFlash(selection) {
64992     var modalSelection = uiModal(selection);
64993
64994     modalSelection.select('.modal')
64995         .classed('modal-flash', true);
64996
64997     modalSelection.select('.content')
64998         .classed('modal-section', true)
64999         .append('div')
65000         .attr('class', 'description');
65001
65002     modalSelection.on('click.flash', function() {
65003         modalSelection.remove();
65004     });
65005
65006     setTimeout(function() {
65007         modalSelection.remove();
65008         return true;
65009     }, 1500);
65010
65011
65012     return modalSelection;
65013 }
65014
65015 function uiLasso(context) {
65016     var group, polygon;
65017
65018     lasso.coordinates = [];
65019
65020     function lasso(selection$$1) {
65021         context.container()
65022             .classed('lasso', true);
65023
65024         group = selection$$1
65025             .append('g')
65026             .attr('class', 'lasso hide');
65027
65028         polygon = group
65029             .append('path')
65030             .attr('class', 'lasso-path');
65031
65032         group
65033             .call(uiToggle(true));
65034     }
65035
65036
65037     function draw() {
65038         if (polygon) {
65039             polygon.data([lasso.coordinates])
65040                 .attr('d', function(d) { return 'M' + d.join(' L') + ' Z'; });
65041         }
65042     }
65043
65044
65045     lasso.extent = function () {
65046         return lasso.coordinates.reduce(function(extent$$1, point) {
65047             return extent$$1.extend(geoExtent$$1(point));
65048         }, geoExtent$$1());
65049     };
65050
65051
65052     lasso.p = function(_) {
65053         if (!arguments.length) return lasso;
65054         lasso.coordinates.push(_);
65055         draw();
65056         return lasso;
65057     };
65058
65059
65060     lasso.close = function() {
65061         if (group) {
65062             group.call(uiToggle(false, function() {
65063                 select(this).remove();
65064             }));
65065         }
65066         context.container().classed('lasso', false);
65067     };
65068
65069
65070     return lasso;
65071 }
65072
65073 function uiRadialMenu(context, operations) {
65074     var menu,
65075         center = [0, 0],
65076         tooltip;
65077
65078
65079     var radialMenu = function(selection$$1) {
65080         if (!operations.length) return;
65081
65082         selection$$1.node().parentNode.focus();
65083
65084         function click(operation) {
65085             event.stopPropagation();
65086             if (operation.disabled()) return;
65087             operation();
65088             radialMenu.close();
65089         }
65090
65091         menu = selection$$1
65092             .append('g')
65093             .attr('class', 'radial-menu')
65094             .attr('transform', 'translate(' + center + ')')
65095             .attr('opacity', 0);
65096
65097         menu
65098             .transition()
65099             .attr('opacity', 1);
65100
65101         var r = 50,
65102             a = Math.PI / 4,
65103             a0 = -Math.PI / 4,
65104             a1 = a0 + (operations.length - 1) * a;
65105
65106         menu
65107             .append('path')
65108             .attr('class', 'radial-menu-background')
65109             .attr('d', 'M' + r * Math.sin(a0) + ',' +
65110                              r * Math.cos(a0) +
65111                       ' A' + r + ',' + r + ' 0 ' + (operations.length > 5 ? '1' : '0') + ',0 ' +
65112                              (r * Math.sin(a1) + 1e-3) + ',' +
65113                              (r * Math.cos(a1) + 1e-3)) // Force positive-length path (#1305)
65114             .attr('stroke-width', 50)
65115             .attr('stroke-linecap', 'round');
65116
65117         var button = menu.selectAll()
65118             .data(operations)
65119             .enter()
65120             .append('g')
65121             .attr('class', function(d) { return 'radial-menu-item radial-menu-item-' + d.id; })
65122             .classed('disabled', function(d) { return d.disabled(); })
65123             .attr('transform', function(d, i) {
65124                 return 'translate(' + geoRoundCoords([
65125                         r * Math.sin(a0 + i * a),
65126                         r * Math.cos(a0 + i * a)]).join(',') + ')';
65127             });
65128
65129         button
65130             .append('circle')
65131             .attr('r', 15)
65132             .on('click', click)
65133             .on('mousedown', mousedown)
65134             .on('mouseover', mouseover)
65135             .on('mouseout', mouseout);
65136
65137         button
65138             .append('use')
65139             .attr('transform', 'translate(-10,-10)')
65140             .attr('width', '20')
65141             .attr('height', '20')
65142             .attr('xlink:href', function(d) { return '#operation-' + d.id; });
65143
65144         tooltip = select(document.body)
65145             .append('div')
65146             .attr('class', 'tooltip-inner radial-menu-tooltip');
65147
65148         function mousedown() {
65149             event.stopPropagation(); // https://github.com/openstreetmap/iD/issues/1869
65150         }
65151
65152         function mouseover(d, i) {
65153             var rect = context.surfaceRect(),
65154                 angle = a0 + i * a,
65155                 top = rect.top + (r + 25) * Math.cos(angle) + center[1] + 'px',
65156                 left = rect.left + (r + 25) * Math.sin(angle) + center[0] + 'px',
65157                 bottom = rect.height - (r + 25) * Math.cos(angle) - center[1] + 'px',
65158                 right = rect.width - (r + 25) * Math.sin(angle) - center[0] + 'px';
65159
65160             tooltip
65161                 .style('top', null)
65162                 .style('left', null)
65163                 .style('bottom', null)
65164                 .style('right', null)
65165                 .style('display', 'block')
65166                 .html(uiTooltipHtml(d.tooltip(), d.keys[0]));
65167
65168             if (i === 0) {
65169                 tooltip
65170                     .style('right', right)
65171                     .style('top', top);
65172             } else if (i >= 4) {
65173                 tooltip
65174                     .style('left', left)
65175                     .style('bottom', bottom);
65176             } else {
65177                 tooltip
65178                     .style('left', left)
65179                     .style('top', top);
65180             }
65181         }
65182
65183         function mouseout() {
65184             tooltip.style('display', 'none');
65185         }
65186     };
65187
65188
65189     radialMenu.close = function() {
65190         if (menu) {
65191             menu
65192                 .style('pointer-events', 'none')
65193                 .transition()
65194                 .attr('opacity', 0)
65195                 .remove();
65196         }
65197
65198         if (tooltip) {
65199             tooltip.remove();
65200         }
65201     };
65202
65203
65204     radialMenu.center = function(_) {
65205         if (!arguments.length) return center;
65206         center = _;
65207         return radialMenu;
65208     };
65209
65210
65211     return radialMenu;
65212 }
65213
65214 function uiSelectionList(context, selectedIDs) {
65215
65216     function selectEntity(entity) {
65217         context.enter(modeSelect(context, [entity.id]).suppressMenu(true));
65218     }
65219
65220
65221     function deselectEntity(entity) {
65222         event.stopPropagation();
65223         var index = selectedIDs.indexOf(entity.id);
65224         if (index > -1) {
65225             selectedIDs.splice(index, 1);
65226         }
65227         context.enter(modeSelect(context, selectedIDs).suppressMenu(true));
65228     }
65229
65230
65231     function selectionList(selection$$1) {
65232         selection$$1.classed('selection-list-pane', true);
65233
65234         var header = selection$$1
65235             .append('div')
65236             .attr('class', 'header fillL cf');
65237
65238         header
65239             .append('h3')
65240             .text(t('inspector.multiselect'));
65241
65242         var listWrap = selection$$1
65243             .append('div')
65244             .attr('class', 'inspector-body');
65245
65246         var list = listWrap
65247             .append('div')
65248             .attr('class', 'feature-list cf');
65249
65250         context.history().on('change.selection-list', drawList);
65251         drawList();
65252
65253
65254         function drawList() {
65255             var entities = selectedIDs
65256                 .map(function(id) { return context.hasEntity(id); })
65257                 .filter(function(entity) { return entity; });
65258
65259             var items = list.selectAll('.feature-list-item')
65260                 .data(entities, osmEntity$$1.key);
65261
65262             items.exit()
65263                 .remove();
65264
65265             // Enter
65266             var enter = items.enter()
65267                 .append('div')
65268                 .attr('class', 'feature-list-item')
65269                 .on('click', selectEntity);
65270
65271             var label = enter
65272                 .append('button')
65273                 .attr('class', 'label');
65274
65275             enter
65276                 .append('button')
65277                 .attr('class', 'close')
65278                 .on('click', deselectEntity)
65279                 .call(svgIcon('#icon-close'));
65280
65281             label
65282                 .append('span')
65283                 .attr('class', 'entity-geom-icon')
65284                 .call(svgIcon('', 'pre-text'));
65285
65286             label
65287                 .append('span')
65288                 .attr('class', 'entity-type');
65289
65290             label
65291                 .append('span')
65292                 .attr('class', 'entity-name');
65293
65294             // Update
65295             items = items.merge(enter);
65296
65297             items.selectAll('.entity-geom-icon use')
65298                 .attr('href', function() {
65299                     var entity = this.parentNode.parentNode.__data__;
65300                     return '#icon-' + context.geometry(entity.id);
65301                 });
65302
65303             items.selectAll('.entity-type')
65304                 .text(function(entity) { return context.presets().match(entity, context.graph()).name(); });
65305
65306             items.selectAll('.entity-name')
65307                 .text(function(entity) { return utilDisplayName(entity); });
65308         }
65309     }
65310
65311     return selectionList;
65312 }
65313
65314 function uiSourceSwitch(context) {
65315     var keys$$1;
65316
65317
65318     function click() {
65319         event.preventDefault();
65320
65321         if (context.history().hasChanges() &&
65322             !window.confirm(t('source_switch.lose_changes'))) return;
65323
65324         var live = select(this)
65325             .classed('live');
65326
65327         context.connection()
65328             .switch(live ? keys$$1[1] : keys$$1[0]);
65329
65330         context.enter(modeBrowse$$1(context));
65331         context.flush();
65332
65333         select(this)
65334             .text(live ? t('source_switch.dev') : t('source_switch.live'))
65335             .classed('live', !live);
65336     }
65337
65338     var sourceSwitch = function(selection$$1) {
65339         selection$$1
65340             .append('a')
65341             .attr('href', '#')
65342             .text(t('source_switch.live'))
65343             .classed('live', true)
65344             .attr('tabindex', -1)
65345             .on('click', click);
65346     };
65347
65348
65349     sourceSwitch.keys = function(_) {
65350         if (!arguments.length) return keys$$1;
65351         keys$$1 = _;
65352         return sourceSwitch;
65353     };
65354
65355
65356     return sourceSwitch;
65357 }
65358
65359 function uiSuccess(context) {
65360     var dispatch$$1 = dispatch('cancel'),
65361         changeset;
65362
65363
65364     function success(selection$$1) {
65365         var message = (changeset.comment || t('success.edited_osm')).substring(0, 130) +
65366             ' ' + context.connection().changesetURL(changeset.id);
65367
65368         var header = selection$$1
65369             .append('div')
65370             .attr('class', 'header fillL');
65371
65372         header
65373             .append('button')
65374             .attr('class', 'fr')
65375             .on('click', function() { dispatch$$1.call('cancel'); })
65376             .call(svgIcon('#icon-close'));
65377
65378         header
65379             .append('h3')
65380             .text(t('success.just_edited'));
65381
65382         var body = selection$$1
65383             .append('div')
65384             .attr('class', 'body save-success fillL');
65385
65386         body
65387             .append('p')
65388             .html(t('success.help_html'));
65389
65390         body
65391             .append('a')
65392             .attr('class', 'details')
65393             .attr('target', '_blank')
65394             .attr('tabindex', -1)
65395             .call(svgIcon('#icon-out-link', 'inline'))
65396             .attr('href', t('success.help_link_url'))
65397             .append('span')
65398             .text(t('success.help_link_text'));
65399
65400         var changesetURL = context.connection().changesetURL(changeset.id);
65401
65402         body
65403             .append('a')
65404             .attr('class', 'button col12 osm')
65405             .attr('target', '_blank')
65406             .attr('href', changesetURL)
65407             .text(t('success.view_on_osm'));
65408
65409         var sharing = {
65410             facebook: 'https://facebook.com/sharer/sharer.php?u=' + encodeURIComponent(changesetURL),
65411             twitter: 'https://twitter.com/intent/tweet?source=webclient&text=' + encodeURIComponent(message),
65412             google: 'https://plus.google.com/share?url=' + encodeURIComponent(changesetURL)
65413         };
65414
65415         body.selectAll('.button.social')
65416             .data(entries(sharing))
65417             .enter()
65418             .append('a')
65419             .attr('class', 'button social col4')
65420             .attr('target', '_blank')
65421             .attr('href', function(d) { return d.value; })
65422             .call(tooltip()
65423                 .title(function(d) { return t('success.' + d.key); })
65424                 .placement('bottom'))
65425             .each(function(d) { select(this).call(svgIcon('#logo-' + d.key, 'social')); });
65426     }
65427
65428
65429     success.changeset = function(_) {
65430         if (!arguments.length) return changeset;
65431         changeset = _;
65432         return success;
65433     };
65434
65435
65436     return utilRebind(success, dispatch$$1, 'on');
65437 }
65438
65439 function coreHistory(context) {
65440     var stack$$1, index, tree$$1,
65441         imageryUsed = ['Bing'],
65442         dispatch$$1 = dispatch('change', 'undone', 'redone'),
65443         lock = utilSessionMutex('lock');
65444
65445
65446     function perform(actions) {
65447         actions = Array.prototype.slice.call(actions);
65448
65449         var annotation;
65450
65451         if (!lodash.isFunction(lodash.last(actions))) {
65452             annotation = actions.pop();
65453         }
65454
65455         var graph = stack$$1[index].graph;
65456         for (var i = 0; i < actions.length; i++) {
65457             graph = actions[i](graph);
65458         }
65459
65460         return {
65461             graph: graph,
65462             annotation: annotation,
65463             imageryUsed: imageryUsed
65464         };
65465     }
65466
65467
65468     function change(previous) {
65469         var difference = coreDifference(previous, history.graph());
65470         dispatch$$1.call('change', this, difference);
65471         return difference;
65472     }
65473
65474
65475     // iD uses namespaced keys so multiple installations do not conflict
65476     function getKey(n) {
65477         return 'iD_' + window.location.origin + '_' + n;
65478     }
65479
65480
65481     var history = {
65482
65483         graph: function() {
65484             return stack$$1[index].graph;
65485         },
65486
65487
65488         base: function() {
65489             return stack$$1[0].graph;
65490         },
65491
65492
65493         merge: function(entities, extent$$1) {
65494             stack$$1[0].graph.rebase(entities, lodash.map(stack$$1, 'graph'), false);
65495             tree$$1.rebase(entities, false);
65496
65497             dispatch$$1.call('change', this, undefined, extent$$1);
65498         },
65499
65500
65501         perform: function() {
65502             var previous = stack$$1[index].graph;
65503
65504             stack$$1 = stack$$1.slice(0, index + 1);
65505             stack$$1.push(perform(arguments));
65506             index++;
65507
65508             return change(previous);
65509         },
65510
65511
65512         replace: function() {
65513             var previous = stack$$1[index].graph;
65514
65515             // assert(index == stack.length - 1)
65516             stack$$1[index] = perform(arguments);
65517
65518             return change(previous);
65519         },
65520
65521
65522         pop: function() {
65523             var previous = stack$$1[index].graph;
65524
65525             if (index > 0) {
65526                 index--;
65527                 stack$$1.pop();
65528                 return change(previous);
65529             }
65530         },
65531
65532
65533         // Same as calling pop and then perform
65534         overwrite: function() {
65535             var previous = stack$$1[index].graph;
65536
65537             if (index > 0) {
65538                 index--;
65539                 stack$$1.pop();
65540             }
65541             stack$$1 = stack$$1.slice(0, index + 1);
65542             stack$$1.push(perform(arguments));
65543             index++;
65544
65545             return change(previous);
65546         },
65547
65548
65549         undo: function() {
65550             var previous = stack$$1[index].graph;
65551
65552             // Pop to the next annotated state.
65553             while (index > 0) {
65554                 index--;
65555                 if (stack$$1[index].annotation) break;
65556             }
65557
65558             dispatch$$1.call('undone');
65559             return change(previous);
65560         },
65561
65562
65563         redo: function() {
65564             var previous = stack$$1[index].graph;
65565
65566             while (index < stack$$1.length - 1) {
65567                 index++;
65568                 if (stack$$1[index].annotation) break;
65569             }
65570
65571             dispatch$$1.call('redone');
65572             return change(previous);
65573         },
65574
65575
65576         undoAnnotation: function() {
65577             var i = index;
65578             while (i >= 0) {
65579                 if (stack$$1[i].annotation) return stack$$1[i].annotation;
65580                 i--;
65581             }
65582         },
65583
65584
65585         redoAnnotation: function() {
65586             var i = index + 1;
65587             while (i <= stack$$1.length - 1) {
65588                 if (stack$$1[i].annotation) return stack$$1[i].annotation;
65589                 i++;
65590             }
65591         },
65592
65593
65594         intersects: function(extent$$1) {
65595             return tree$$1.intersects(extent$$1, stack$$1[index].graph);
65596         },
65597
65598
65599         difference: function() {
65600             var base = stack$$1[0].graph,
65601                 head = stack$$1[index].graph;
65602             return coreDifference(base, head);
65603         },
65604
65605
65606         changes: function(action) {
65607             var base = stack$$1[0].graph,
65608                 head = stack$$1[index].graph;
65609
65610             if (action) {
65611                 head = action(head);
65612             }
65613
65614             var difference = coreDifference(base, head);
65615
65616             return {
65617                 modified: difference.modified(),
65618                 created: difference.created(),
65619                 deleted: difference.deleted()
65620             };
65621         },
65622
65623
65624         validate: function(changes) {
65625             return lodash(Validations)
65626                 .map(function(fn) { return fn()(changes, stack$$1[index].graph); })
65627                 .flatten()
65628                 .value();
65629         },
65630
65631
65632         hasChanges: function() {
65633             return this.difference().length() > 0;
65634         },
65635
65636
65637         imageryUsed: function(sources) {
65638             if (sources) {
65639                 imageryUsed = sources;
65640                 return history;
65641             } else {
65642                 return lodash(stack$$1.slice(1, index + 1))
65643                     .map('imageryUsed')
65644                     .flatten()
65645                     .uniq()
65646                     .without(undefined, 'Custom')
65647                     .value();
65648             }
65649         },
65650
65651
65652         reset: function() {
65653             stack$$1 = [{graph: coreGraph$$1()}];
65654             index = 0;
65655             tree$$1 = coreTree(stack$$1[0].graph);
65656             dispatch$$1.call('change');
65657             return history;
65658         },
65659
65660
65661         toJSON: function() {
65662             if (!this.hasChanges()) return;
65663
65664             var allEntities = {},
65665                 baseEntities = {},
65666                 base = stack$$1[0];
65667
65668             var s = stack$$1.map(function(i) {
65669                 var modified = [], deleted = [];
65670
65671                 lodash.forEach(i.graph.entities, function(entity, id) {
65672                     if (entity) {
65673                         var key = osmEntity$$1.key(entity);
65674                         allEntities[key] = entity;
65675                         modified.push(key);
65676                     } else {
65677                         deleted.push(id);
65678                     }
65679
65680                     // make sure that the originals of changed or deleted entities get merged
65681                     // into the base of the stack after restoring the data from JSON.
65682                     if (id in base.graph.entities) {
65683                         baseEntities[id] = base.graph.entities[id];
65684                     }
65685                     // get originals of parent entities too
65686                     lodash.forEach(base.graph._parentWays[id], function(parentId) {
65687                         if (parentId in base.graph.entities) {
65688                             baseEntities[parentId] = base.graph.entities[parentId];
65689                         }
65690                     });
65691                 });
65692
65693                 var x = {};
65694
65695                 if (modified.length) x.modified = modified;
65696                 if (deleted.length) x.deleted = deleted;
65697                 if (i.imageryUsed) x.imageryUsed = i.imageryUsed;
65698                 if (i.annotation) x.annotation = i.annotation;
65699
65700                 return x;
65701             });
65702
65703             return JSON.stringify({
65704                 version: 3,
65705                 entities: lodash.values(allEntities),
65706                 baseEntities: lodash.values(baseEntities),
65707                 stack: s,
65708                 nextIDs: osmEntity$$1.id.next,
65709                 index: index
65710             });
65711         },
65712
65713
65714         fromJSON: function(json$$1, loadChildNodes) {
65715             var h = JSON.parse(json$$1),
65716                 loadComplete = true;
65717
65718             osmEntity$$1.id.next = h.nextIDs;
65719             index = h.index;
65720
65721             if (h.version === 2 || h.version === 3) {
65722                 var allEntities = {};
65723
65724                 h.entities.forEach(function(entity) {
65725                     allEntities[osmEntity$$1.key(entity)] = osmEntity$$1(entity);
65726                 });
65727
65728                 if (h.version === 3) {
65729                     // This merges originals for changed entities into the base of
65730                     // the stack even if the current stack doesn't have them (for
65731                     // example when iD has been restarted in a different region)
65732                     var baseEntities = h.baseEntities.map(function(d) { return osmEntity$$1(d); });
65733                     stack$$1[0].graph.rebase(baseEntities, lodash.map(stack$$1, 'graph'), true);
65734                     tree$$1.rebase(baseEntities, true);
65735
65736                     // When we restore a modified way, we also need to fetch any missing
65737                     // childnodes that would normally have been downloaded with it.. #2142
65738                     if (loadChildNodes) {
65739                         var missing =  lodash(baseEntities)
65740                                 .filter({ type: 'way' })
65741                                 .map('nodes')
65742                                 .flatten()
65743                                 .uniq()
65744                                 .reject(function(n) { return stack$$1[0].graph.hasEntity(n); })
65745                                 .value();
65746
65747                         if (!lodash.isEmpty(missing)) {
65748                             loadComplete = false;
65749                             context.redrawEnable(false);
65750
65751                             var loading = uiLoading(context).blocking(true);
65752                             context.container().call(loading);
65753
65754                             var childNodesLoaded = function(err, result) {
65755                                 if (!err) {
65756                                     var visible = lodash.groupBy(result.data, 'visible');
65757                                     if (!lodash.isEmpty(visible.true)) {
65758                                         missing = lodash.difference(missing, lodash.map(visible.true, 'id'));
65759                                         stack$$1[0].graph.rebase(visible.true, lodash.map(stack$$1, 'graph'), true);
65760                                         tree$$1.rebase(visible.true, true);
65761                                     }
65762
65763                                     // fetch older versions of nodes that were deleted..
65764                                     lodash.each(visible.false, function(entity) {
65765                                         context.connection()
65766                                             .loadEntityVersion(entity.id, +entity.version - 1, childNodesLoaded);
65767                                     });
65768                                 }
65769
65770                                 if (err || lodash.isEmpty(missing)) {
65771                                     loading.close();
65772                                     context.redrawEnable(true);
65773                                     dispatch$$1.call('change');
65774                                 }
65775                             };
65776
65777                             context.connection().loadMultiple(missing, childNodesLoaded);
65778                         }
65779                     }
65780                 }
65781
65782                 stack$$1 = h.stack.map(function(d) {
65783                     var entities = {}, entity;
65784
65785                     if (d.modified) {
65786                         d.modified.forEach(function(key) {
65787                             entity = allEntities[key];
65788                             entities[entity.id] = entity;
65789                         });
65790                     }
65791
65792                     if (d.deleted) {
65793                         d.deleted.forEach(function(id) {
65794                             entities[id] = undefined;
65795                         });
65796                     }
65797
65798                     return {
65799                         graph: coreGraph$$1(stack$$1[0].graph).load(entities),
65800                         annotation: d.annotation,
65801                         imageryUsed: d.imageryUsed
65802                     };
65803                 });
65804
65805             } else { // original version
65806                 stack$$1 = h.stack.map(function(d) {
65807                     var entities = {};
65808
65809                     for (var i in d.entities) {
65810                         var entity = d.entities[i];
65811                         entities[i] = entity === 'undefined' ? undefined : osmEntity$$1(entity);
65812                     }
65813
65814                     d.graph = coreGraph$$1(stack$$1[0].graph).load(entities);
65815                     return d;
65816                 });
65817             }
65818
65819             if (loadComplete) {
65820                 dispatch$$1.call('change');
65821             }
65822
65823             return history;
65824         },
65825
65826
65827         save: function() {
65828             if (lock.locked()) context.storage(getKey('saved_history'), history.toJSON() || null);
65829             return history;
65830         },
65831
65832
65833         clearSaved: function() {
65834             context.debouncedSave.cancel();
65835             if (lock.locked()) context.storage(getKey('saved_history'), null);
65836             return history;
65837         },
65838
65839
65840         lock: function() {
65841             return lock.lock();
65842         },
65843
65844
65845         unlock: function() {
65846             lock.unlock();
65847         },
65848
65849
65850         // is iD not open in another window and it detects that
65851         // there's a history stored in localStorage that's recoverable?
65852         restorableChanges: function() {
65853             return lock.locked() && !!context.storage(getKey('saved_history'));
65854         },
65855
65856
65857         // load history from a version stored in localStorage
65858         restore: function() {
65859             if (!lock.locked()) return;
65860
65861             var json$$1 = context.storage(getKey('saved_history'));
65862             if (json$$1) history.fromJSON(json$$1, true);
65863         },
65864
65865
65866         _getKey: getKey
65867
65868     };
65869
65870
65871     history.reset();
65872
65873     return utilRebind(history, dispatch$$1, 'on');
65874 }
65875
65876 function presetCollection(collection) {
65877     var maxSearchResults = 50,
65878         maxSuggestionResults = 10;
65879
65880     var presets = {
65881
65882         collection: collection,
65883
65884
65885         item: function(id) {
65886             return lodash.find(collection, function(d) {
65887                 return d.id === id;
65888             });
65889         },
65890
65891
65892         matchGeometry: function(geometry) {
65893             return presetCollection(collection.filter(function(d) {
65894                 return d.matchGeometry(geometry);
65895             }));
65896         },
65897
65898
65899         search: function(value, geometry) {
65900             if (!value) return this;
65901
65902             function leading(a) {
65903                 var index = a.indexOf(value);
65904                 return index === 0 || a[index - 1] === ' ';
65905             }
65906
65907             function suggestionName(name) {
65908                 var nameArray = name.split(' - ');
65909                 if (nameArray.length > 1) {
65910                     name = nameArray.slice(0, nameArray.length - 1).join(' - ');
65911                 }
65912                 return name.toLowerCase();
65913             }
65914
65915
65916             value = value.toLowerCase();
65917
65918             var searchable = lodash.filter(collection, function(a) {
65919                     return a.searchable !== false && a.suggestion !== true;
65920                 }),
65921                 suggestions = lodash.filter(collection, function(a) {
65922                     return a.suggestion === true;
65923                 });
65924
65925
65926             // matches value to preset.name
65927             var leading_name = lodash.filter(searchable, function(a) {
65928                     return leading(a.name().toLowerCase());
65929                 }).sort(function(a, b) {
65930                     var i = a.name().toLowerCase().indexOf(value) - b.name().toLowerCase().indexOf(value);
65931                     if (i === 0) return a.name().length - b.name().length;
65932                     else return i;
65933                 });
65934
65935             // matches value to preset.terms values
65936             var leading_terms = lodash.filter(searchable, function(a) {
65937                     return lodash.some(a.terms() || [], leading);
65938                 });
65939
65940             // matches value to preset.tags values
65941             var leading_tag_values = lodash.filter(searchable, function(a) {
65942                     return lodash.some(lodash.without(lodash.values(a.tags || {}), '*'), leading);
65943                 });
65944
65945
65946             // finds close matches to value in preset.name
65947             var similar_name = searchable.map(function(a) {
65948                     return {
65949                         preset: a,
65950                         dist: utilEditDistance(value, a.name())
65951                     };
65952                 }).filter(function(a) {
65953                     return a.dist + Math.min(value.length - a.preset.name().length, 0) < 3;
65954                 }).sort(function(a, b) {
65955                     return a.dist - b.dist;
65956                 }).map(function(a) {
65957                     return a.preset;
65958                 });
65959
65960             // finds close matches to value in preset.terms
65961             var similar_terms = lodash.filter(searchable, function(a) {
65962                     return lodash.some(a.terms() || [], function(b) {
65963                         return utilEditDistance(value, b) + Math.min(value.length - b.length, 0) < 3;
65964                     });
65965                 });
65966
65967             var leading_suggestions = lodash.filter(suggestions, function(a) {
65968                     return leading(suggestionName(a.name()));
65969                 }).sort(function(a, b) {
65970                     a = suggestionName(a.name());
65971                     b = suggestionName(b.name());
65972                     var i = a.indexOf(value) - b.indexOf(value);
65973                     if (i === 0) return a.length - b.length;
65974                     else return i;
65975                 });
65976
65977             var similar_suggestions = suggestions.map(function(a) {
65978                     return {
65979                         preset: a,
65980                         dist: utilEditDistance(value, suggestionName(a.name()))
65981                     };
65982                 }).filter(function(a) {
65983                     return a.dist + Math.min(value.length - suggestionName(a.preset.name()).length, 0) < 1;
65984                 }).sort(function(a, b) {
65985                     return a.dist - b.dist;
65986                 }).map(function(a) {
65987                     return a.preset;
65988                 });
65989
65990             var other = presets.item(geometry);
65991
65992             var results = leading_name.concat(
65993                     leading_terms,
65994                     leading_tag_values,
65995                     leading_suggestions.slice(0, maxSuggestionResults + 5),
65996                     similar_name,
65997                     similar_terms,
65998                     similar_suggestions.slice(0, maxSuggestionResults)
65999                 ).slice(0, maxSearchResults - 1);
66000
66001             return presetCollection(lodash.uniq(results.concat(other)));
66002         }
66003     };
66004
66005
66006     return presets;
66007 }
66008
66009 function presetCategory(id, category, all) {
66010     category = lodash.clone(category);
66011
66012     category.id = id;
66013
66014
66015     category.members = presetCollection(category.members.map(function(id) {
66016         return all.item(id);
66017     }));
66018
66019
66020     category.matchGeometry = function(geometry) {
66021         return category.geometry.indexOf(geometry) >= 0;
66022     };
66023
66024
66025     category.matchScore = function() {
66026         return -1;
66027     };
66028
66029
66030     category.name = function() {
66031         return t('presets.categories.' + id + '.name', {'default': id});
66032     };
66033
66034
66035     category.terms = function() {
66036         return [];
66037     };
66038
66039
66040     return category;
66041 }
66042
66043 function presetField(id, field) {
66044     field = lodash.clone(field);
66045
66046     field.id = id;
66047
66048
66049     field.matchGeometry = function(geometry) {
66050         return !field.geometry || field.geometry === geometry;
66051     };
66052
66053
66054     field.t = function(scope, options) {
66055         return t('presets.fields.' + id + '.' + scope, options);
66056     };
66057
66058
66059     field.label = function() {
66060         return field.t('label', {'default': id});
66061     };
66062
66063
66064     var placeholder = field.placeholder;
66065     field.placeholder = function() {
66066         return field.t('placeholder', {'default': placeholder});
66067     };
66068
66069
66070     return field;
66071 }
66072
66073 function presetPreset(id, preset, fields) {
66074     preset = lodash.clone(preset);
66075
66076     preset.id = id;
66077     preset.fields = (preset.fields || []).map(getFields);
66078     preset.geometry = (preset.geometry || []);
66079
66080
66081     function getFields(f) {
66082         return fields[f];
66083     }
66084
66085
66086     preset.matchGeometry = function(geometry) {
66087         return preset.geometry.indexOf(geometry) >= 0;
66088     };
66089
66090
66091     var matchScore = preset.matchScore || 1;
66092     preset.matchScore = function(entity) {
66093         var tags = preset.tags,
66094             score = 0;
66095
66096         for (var t$$1 in tags) {
66097             if (entity.tags[t$$1] === tags[t$$1]) {
66098                 score += matchScore;
66099             } else if (tags[t$$1] === '*' && t$$1 in entity.tags) {
66100                 score += matchScore / 2;
66101             } else {
66102                 return -1;
66103             }
66104         }
66105
66106         return score;
66107     };
66108
66109
66110     preset.t = function(scope, options) {
66111         return t('presets.presets.' + id + '.' + scope, options);
66112     };
66113
66114
66115     var name = preset.name || '';
66116     preset.name = function() {
66117         if (preset.suggestion) {
66118             id = id.split('/');
66119             id = id[0] + '/' + id[1];
66120             return name + ' - ' + t('presets.presets.' + id + '.name');
66121         }
66122         return preset.t('name', {'default': name});
66123     };
66124
66125
66126     preset.terms = function() {
66127         return preset.t('terms', {'default': ''}).toLowerCase().trim().split(/\s*,+\s*/);
66128     };
66129
66130
66131     preset.isFallback = function() {
66132         var tagCount = Object.keys(preset.tags).length;
66133         return tagCount === 0 || (tagCount === 1 && preset.tags.hasOwnProperty('area'));
66134     };
66135
66136
66137     preset.reference = function(geometry) {
66138         var key = Object.keys(preset.tags)[0],
66139             value = preset.tags[key];
66140
66141         if (geometry === 'relation' && key === 'type') {
66142             if (value in preset.tags) {
66143                 key = value;
66144                 value = preset.tags[key];
66145             } else {
66146                 return { rtype: value };
66147             }
66148         }
66149
66150         if (value === '*') {
66151             return { key: key };
66152         } else {
66153             return { key: key, value: value };
66154         }
66155     };
66156
66157
66158     var removeTags = preset.removeTags || preset.tags;
66159     preset.removeTags = function(tags, geometry) {
66160         tags = lodash.omit(tags, lodash.keys(removeTags));
66161
66162         for (var f in preset.fields) {
66163             var field = preset.fields[f];
66164             if (field.matchGeometry(geometry) && field.default === tags[field.key]) {
66165                 delete tags[field.key];
66166             }
66167         }
66168
66169         delete tags.area;
66170         return tags;
66171     };
66172
66173
66174     var applyTags = preset.addTags || preset.tags;
66175     preset.applyTags = function(tags, geometry) {
66176         var k;
66177
66178         tags = lodash.clone(tags);
66179
66180         for (k in applyTags) {
66181             if (applyTags[k] === '*') {
66182                 tags[k] = 'yes';
66183             } else {
66184                 tags[k] = applyTags[k];
66185             }
66186         }
66187
66188         // Add area=yes if necessary.
66189         // This is necessary if the geometry is already an area (e.g. user drew an area) AND any of:
66190         // 1. chosen preset could be either an area or a line (`barrier=city_wall`)
66191         // 2. chosen preset doesn't have a key in areaKeys (`railway=station`)
66192         if (geometry === 'area') {
66193             var needsAreaTag = true;
66194             if (preset.geometry.indexOf('line') === -1) {
66195                 for (k in applyTags) {
66196                     if (k in areaKeys) {
66197                         needsAreaTag = false;
66198                         break;
66199                     }
66200                 }
66201             }
66202             if (needsAreaTag) {
66203                 tags.area = 'yes';
66204             }
66205         }
66206
66207         for (var f in preset.fields) {
66208             var field = preset.fields[f];
66209             if (field.matchGeometry(geometry) && field.key && !tags[field.key] && field.default) {
66210                 tags[field.key] = field.default;
66211             }
66212         }
66213
66214         return tags;
66215     };
66216
66217
66218     return preset;
66219 }
66220
66221 function presetIndex() {
66222     // a presetCollection with methods for
66223     // loading new data and returning defaults
66224
66225     var all = presetCollection([]),
66226         defaults = { area: all, line: all, point: all, vertex: all, relation: all },
66227         fields = {},
66228         universal = [],
66229         recent = presetCollection([]);
66230
66231     // Index of presets by (geometry, tag key).
66232     var index = {
66233         point: {},
66234         vertex: {},
66235         line: {},
66236         area: {},
66237         relation: {}
66238     };
66239
66240     all.match = function(entity, resolver) {
66241         var geometry = entity.geometry(resolver);
66242
66243         // Treat entities on addr:interpolation lines as points, not vertices (#3241)
66244         if (geometry === 'vertex' && entity.isOnAddressLine(resolver)) {
66245             geometry = 'point';
66246         }
66247
66248         var geometryMatches = index[geometry],
66249             best = -1,
66250             match;
66251
66252         for (var k in entity.tags) {
66253             var keyMatches = geometryMatches[k];
66254             if (!keyMatches) continue;
66255
66256             for (var i = 0; i < keyMatches.length; i++) {
66257                 var score = keyMatches[i].matchScore(entity);
66258                 if (score > best) {
66259                     best = score;
66260                     match = keyMatches[i];
66261                 }
66262             }
66263         }
66264
66265         return match || all.item(geometry);
66266     };
66267
66268
66269     // Because of the open nature of tagging, iD will never have a complete
66270     // list of tags used in OSM, so we want it to have logic like "assume
66271     // that a closed way with an amenity tag is an area, unless the amenity
66272     // is one of these specific types". This function computes a structure
66273     // that allows testing of such conditions, based on the presets designated
66274     // as as supporting (or not supporting) the area geometry.
66275     //
66276     // The returned object L is a whitelist/blacklist of tags. A closed way
66277     // with a tag (k, v) is considered to be an area if `k in L && !(v in L[k])`
66278     // (see `Way#isArea()`). In other words, the keys of L form the whitelist,
66279     // and the subkeys form the blacklist.
66280     all.areaKeys = function() {
66281         var areaKeys = {},
66282             ignore = ['barrier', 'highway', 'footway', 'railway', 'type'],
66283             presets = lodash.reject(all.collection, 'suggestion');
66284
66285         // whitelist
66286         presets.forEach(function(d) {
66287             for (var key in d.tags) break;
66288             if (!key) return;
66289             if (ignore.indexOf(key) !== -1) return;
66290
66291             if (d.geometry.indexOf('area') !== -1) {
66292                 areaKeys[key] = areaKeys[key] || {};
66293             }
66294         });
66295
66296         // blacklist
66297         presets.forEach(function(d) {
66298             for (var key in d.tags) break;
66299             if (!key) return;
66300             if (ignore.indexOf(key) !== -1) return;
66301
66302             var value = d.tags[key];
66303             if (d.geometry.indexOf('area') === -1 &&
66304                 d.geometry.indexOf('line') !== -1 &&
66305                 key in areaKeys && value !== '*') {
66306                 areaKeys[key][value] = true;
66307             }
66308         });
66309
66310         return areaKeys;
66311     };
66312
66313
66314     all.init = function() {
66315         var d = data.presets;
66316
66317         if (d.fields) {
66318             lodash.forEach(d.fields, function(d, id) {
66319                 fields[id] = presetField(id, d);
66320                 if (d.universal) universal.push(fields[id]);
66321             });
66322         }
66323
66324         if (d.presets) {
66325             lodash.forEach(d.presets, function(d, id) {
66326                 all.collection.push(presetPreset(id, d, fields));
66327             });
66328         }
66329
66330         if (d.categories) {
66331             lodash.forEach(d.categories, function(d, id) {
66332                 all.collection.push(presetCategory(id, d, all));
66333             });
66334         }
66335
66336         if (d.defaults) {
66337             var getItem = lodash.bind(all.item, all);
66338             defaults = {
66339                 area: presetCollection(d.defaults.area.map(getItem)),
66340                 line: presetCollection(d.defaults.line.map(getItem)),
66341                 point: presetCollection(d.defaults.point.map(getItem)),
66342                 vertex: presetCollection(d.defaults.vertex.map(getItem)),
66343                 relation: presetCollection(d.defaults.relation.map(getItem))
66344             };
66345         }
66346
66347         for (var i = 0; i < all.collection.length; i++) {
66348             var preset = all.collection[i],
66349                 geometry = preset.geometry;
66350
66351             for (var j = 0; j < geometry.length; j++) {
66352                 var g = index[geometry[j]];
66353                 for (var k in preset.tags) {
66354                     (g[k] = g[k] || []).push(preset);
66355                 }
66356             }
66357         }
66358
66359         return all;
66360     };
66361
66362     all.field = function(id) {
66363         return fields[id];
66364     };
66365
66366     all.universal = function() {
66367         return universal;
66368     };
66369
66370     all.defaults = function(geometry, n) {
66371         var rec = recent.matchGeometry(geometry).collection.slice(0, 4),
66372             def = lodash.uniq(rec.concat(defaults[geometry].collection)).slice(0, n - 1);
66373         return presetCollection(lodash.uniq(rec.concat(def).concat(all.item(geometry))));
66374     };
66375
66376     all.choose = function(preset) {
66377         if (!preset.isFallback()) {
66378             recent = presetCollection(lodash.uniq([preset].concat(recent.collection)));
66379         }
66380         return all;
66381     };
66382
66383     return all;
66384 }
66385
66386 var areaKeys = {};
66387
66388 function setAreaKeys(value) {
66389     areaKeys = value;
66390 }
66391
66392
66393 function coreContext() {
66394     addTranslation('en', en);
66395     setLocale('en');
66396
66397     var dispatch$$1 = dispatch('enter', 'exit', 'change'),
66398         context = {};
66399
66400     // https://github.com/openstreetmap/iD/issues/772
66401     // http://mathiasbynens.be/notes/localstorage-pattern#comment-9
66402     var storage;
66403     try { storage = localStorage; } catch (e) {}  // eslint-disable-line no-empty
66404     storage = storage || (function() {
66405         var s = {};
66406         return {
66407             getItem: function(k) { return s[k]; },
66408             setItem: function(k, v) { s[k] = v; },
66409             removeItem: function(k) { delete s[k]; }
66410         };
66411     })();
66412
66413     context.storage = function(k, v) {
66414         try {
66415             if (arguments.length === 1) return storage.getItem(k);
66416             else if (v === null) storage.removeItem(k);
66417             else storage.setItem(k, v);
66418         } catch (e) {
66419             // localstorage quota exceeded
66420             /* eslint-disable no-console */
66421             if (typeof console !== 'undefined') console.error('localStorage quota exceeded');
66422             /* eslint-enable no-console */
66423         }
66424     };
66425
66426
66427     /* Straight accessors. Avoid using these if you can. */
66428     var ui, connection, history;
66429     context.ui = function() { return ui; };
66430     context.connection = function() { return connection; };
66431     context.history = function() { return history; };
66432
66433
66434     /* Connection */
66435     function entitiesLoaded(err, result) {
66436         if (!err) history.merge(result.data, result.extent);
66437     }
66438
66439     context.preauth = function(options) {
66440         connection.switch(options);
66441         return context;
66442     };
66443
66444     context.loadTiles = function(projection, dimensions, callback) {
66445         function done(err, result) {
66446             entitiesLoaded(err, result);
66447             if (callback) callback(err, result);
66448         }
66449         connection.loadTiles(projection, dimensions, done);
66450     };
66451
66452     context.loadEntity = function(id, callback) {
66453         function done(err, result) {
66454             entitiesLoaded(err, result);
66455             if (callback) callback(err, result);
66456         }
66457         connection.loadEntity(id, done);
66458     };
66459
66460     context.zoomToEntity = function(id, zoomTo) {
66461         if (zoomTo !== false) {
66462             this.loadEntity(id, function(err, result) {
66463                 if (err) return;
66464                 var entity = lodash.find(result.data, function(e) { return e.id === id; });
66465                 if (entity) { map$$1.zoomTo(entity); }
66466             });
66467         }
66468
66469         map$$1.on('drawn.zoomToEntity', function() {
66470             if (!context.hasEntity(id)) return;
66471             map$$1.on('drawn.zoomToEntity', null);
66472             context.on('enter.zoomToEntity', null);
66473             context.enter(modeSelect(context, [id]));
66474         });
66475
66476         context.on('enter.zoomToEntity', function() {
66477             if (mode.id !== 'browse') {
66478                 map$$1.on('drawn.zoomToEntity', null);
66479                 context.on('enter.zoomToEntity', null);
66480             }
66481         });
66482     };
66483
66484     var minEditableZoom = 16;
66485     context.minEditableZoom = function(_) {
66486         if (!arguments.length) return minEditableZoom;
66487         minEditableZoom = _;
66488         connection.tileZoom(_);
66489         return context;
66490     };
66491
66492
66493     /* History */
66494     var inIntro = false;
66495     context.inIntro = function(_) {
66496         if (!arguments.length) return inIntro;
66497         inIntro = _;
66498         return context;
66499     };
66500
66501     context.save = function() {
66502         if (inIntro || (mode && mode.id === 'save') || select('.modal').size()) return;
66503         history.save();
66504         if (history.hasChanges()) return t('save.unsaved_changes');
66505     };
66506
66507
66508     /* Graph */
66509     context.hasEntity = function(id) {
66510         return history.graph().hasEntity(id);
66511     };
66512     context.entity = function(id) {
66513         return history.graph().entity(id);
66514     };
66515     context.childNodes = function(way) {
66516         return history.graph().childNodes(way);
66517     };
66518     context.geometry = function(id) {
66519         return context.entity(id).geometry(history.graph());
66520     };
66521
66522
66523     /* Modes */
66524     var mode;
66525     context.mode = function() {
66526         return mode;
66527     };
66528     context.enter = function(newMode) {
66529         if (mode) {
66530             mode.exit();
66531             dispatch$$1.call('exit', this, mode);
66532         }
66533
66534         mode = newMode;
66535         mode.enter();
66536         dispatch$$1.call('enter', this, mode);
66537     };
66538
66539     context.selectedIDs = function() {
66540         if (mode && mode.selectedIDs) {
66541             return mode.selectedIDs();
66542         } else {
66543             return [];
66544         }
66545     };
66546
66547
66548     /* Behaviors */
66549     context.install = function(behavior) {
66550         context.surface().call(behavior);
66551     };
66552     context.uninstall = function(behavior) {
66553         context.surface().call(behavior.off);
66554     };
66555
66556
66557     /* Copy/Paste */
66558     var copyIDs = [], copyGraph;
66559     context.copyGraph = function() { return copyGraph; };
66560     context.copyIDs = function(_) {
66561         if (!arguments.length) return copyIDs;
66562         copyIDs = _;
66563         copyGraph = history.graph();
66564         return context;
66565     };
66566
66567
66568     /* Background */
66569     var background;
66570     context.background = function() { return background; };
66571
66572
66573     /* Features */
66574     var features;
66575     context.features = function() { return features; };
66576     context.hasHiddenConnections = function(id) {
66577         var graph = history.graph(),
66578             entity = graph.entity(id);
66579         return features.hasHiddenConnections(entity, graph);
66580     };
66581
66582
66583     /* Presets */
66584     var presets;
66585     context.presets = function() { return presets; };
66586
66587
66588     /* Map */
66589     var map$$1;
66590     context.map = function() { return map$$1; };
66591     context.layers = function() { return map$$1.layers; };
66592     context.surface = function() { return map$$1.surface; };
66593     context.editable = function() { return map$$1.editable(); };
66594
66595     context.surfaceRect = function() {
66596         // Work around a bug in Firefox.
66597         //   http://stackoverflow.com/questions/18153989/
66598         //   https://bugzilla.mozilla.org/show_bug.cgi?id=530985
66599         return context.surface().node().parentNode.getBoundingClientRect();
66600     };
66601
66602
66603     /* Debug */
66604     var debugFlags = {
66605         tile: false,
66606         collision: false,
66607         imagery: false,
66608         imperial: false,
66609         driveLeft: false
66610     };
66611     context.debugFlags = function() {
66612         return debugFlags;
66613     };
66614     context.setDebug = function(flag, val) {
66615         if (arguments.length === 1) val = true;
66616         debugFlags[flag] = val;
66617         dispatch$$1.call('change');
66618         return context;
66619     };
66620     context.getDebug = function(flag) {
66621         return flag && debugFlags[flag];
66622     };
66623
66624
66625     /* Container */
66626     var container, embed;
66627     context.container = function(_) {
66628         if (!arguments.length) return container;
66629         container = _;
66630         container.classed('id-container', true);
66631         return context;
66632     };
66633     context.embed = function(_) {
66634         if (!arguments.length) return embed;
66635         embed = _;
66636         return context;
66637     };
66638
66639
66640     /* Assets */
66641     var assetPath = '';
66642     context.assetPath = function(_) {
66643         if (!arguments.length) return assetPath;
66644         assetPath = _;
66645         return context;
66646     };
66647
66648     var assetMap = {};
66649     context.assetMap = function(_) {
66650         if (!arguments.length) return assetMap;
66651         assetMap = _;
66652         return context;
66653     };
66654
66655     context.asset = function(_) {
66656         var filename = assetPath + _;
66657         return assetMap[filename] || filename;
66658     };
66659
66660     context.imagePath = function(_) {
66661         return context.asset('img/' + _);
66662     };
66663
66664
66665     /* locales */
66666     // `locale` variable contains a "requested locale".
66667     // It won't become the `currentLocale` until after loadLocale() is called.
66668     var locale, localePath;
66669
66670     context.locale = function(loc, path$$1) {
66671         if (!arguments.length) return currentLocale;
66672         locale = loc;
66673         localePath = path$$1;
66674         return context;
66675     };
66676
66677     context.loadLocale = function(callback) {
66678         if (locale && locale !== 'en' && dataLocales.indexOf(locale) !== -1) {
66679             localePath = localePath || context.asset('locales/' + locale + '.json');
66680             json(localePath, function(err, result) {
66681                 if (!err) {
66682                     addTranslation(locale, result[locale]);
66683                     setLocale(locale);
66684                     utilDetect(true);
66685                 }
66686                 if (callback) {
66687                     callback(err);
66688                 }
66689             });
66690         } else {
66691             if (locale) {
66692                 setLocale(locale);
66693                 utilDetect(true);
66694             }
66695             if (callback) {
66696                 callback();
66697             }
66698         }
66699     };
66700
66701
66702     /* reset (aka flush) */
66703     context.reset = context.flush = function() {
66704         context.debouncedSave.cancel();
66705         lodash.each(services, function(service) {
66706             if (service && typeof service.reset === 'function') {
66707                 service.reset(context);
66708             }
66709         });
66710         features.reset();
66711         history.reset();
66712         return context;
66713     };
66714
66715
66716     /* Init */
66717     context.version = '2.0.0';
66718
66719     context.projection = geoRawMercator();
66720
66721     locale = utilDetect().locale;
66722     if (locale && dataLocales.indexOf(locale) === -1) {
66723         locale = locale.split('-')[0];
66724     }
66725
66726     history = coreHistory(context);
66727     context.graph = history.graph;
66728     context.changes = history.changes;
66729     context.intersects = history.intersects;
66730
66731     // Debounce save, since it's a synchronous localStorage write,
66732     // and history changes can happen frequently (e.g. when dragging).
66733     context.debouncedSave = lodash.debounce(context.save, 350);
66734     function withDebouncedSave(fn) {
66735         return function() {
66736             var result = fn.apply(history, arguments);
66737             context.debouncedSave();
66738             return result;
66739         };
66740     }
66741
66742     context.perform = withDebouncedSave(history.perform);
66743     context.replace = withDebouncedSave(history.replace);
66744     context.pop = withDebouncedSave(history.pop);
66745     context.overwrite = withDebouncedSave(history.overwrite);
66746     context.undo = withDebouncedSave(history.undo);
66747     context.redo = withDebouncedSave(history.redo);
66748
66749     ui = uiInit(context);
66750
66751     connection = services.osm;
66752
66753     background = rendererBackground(context);
66754     features = rendererFeatures(context);
66755     presets = presetIndex();
66756
66757     map$$1 = rendererMap(context);
66758     context.mouse = map$$1.mouse;
66759     context.extent = map$$1.extent;
66760     context.pan = map$$1.pan;
66761     context.zoomIn = map$$1.zoomIn;
66762     context.zoomOut = map$$1.zoomOut;
66763     context.zoomInFurther = map$$1.zoomInFurther;
66764     context.zoomOutFurther = map$$1.zoomOutFurther;
66765     context.redrawEnable = map$$1.redrawEnable;
66766
66767     background.init();
66768     presets.init();
66769     areaKeys = presets.areaKeys();
66770
66771     lodash.each(services, function(service) {
66772         if (service && typeof service.init === 'function') {
66773             service.init(context);
66774         }
66775     });
66776
66777
66778     return utilRebind(context, dispatch$$1, 'on');
66779 }
66780
66781 function osmWay() {
66782     if (!(this instanceof osmWay)) {
66783         return (new osmWay()).initialize(arguments);
66784     } else if (arguments.length) {
66785         this.initialize(arguments);
66786     }
66787 }
66788
66789
66790 osmEntity$$1.way = osmWay;
66791
66792 osmWay.prototype = Object.create(osmEntity$$1.prototype);
66793
66794
66795 lodash.extend(osmWay.prototype, {
66796     type: 'way',
66797     nodes: [],
66798
66799
66800     copy: function(resolver, copies) {
66801         if (copies[this.id])
66802             return copies[this.id];
66803
66804         var copy = osmEntity$$1.prototype.copy.call(this, resolver, copies);
66805
66806         var nodes = this.nodes.map(function(id) {
66807             return resolver.entity(id).copy(resolver, copies).id;
66808         });
66809
66810         copy = copy.update({ nodes: nodes });
66811         copies[this.id] = copy;
66812
66813         return copy;
66814     },
66815
66816
66817     extent: function(resolver) {
66818         return resolver.transient(this, 'extent', function() {
66819             var extent$$1 = geoExtent$$1();
66820             for (var i = 0; i < this.nodes.length; i++) {
66821                 var node = resolver.hasEntity(this.nodes[i]);
66822                 if (node) {
66823                     extent$$1._extend(node.extent());
66824                 }
66825             }
66826             return extent$$1;
66827         });
66828     },
66829
66830
66831     first: function() {
66832         return this.nodes[0];
66833     },
66834
66835
66836     last: function() {
66837         return this.nodes[this.nodes.length - 1];
66838     },
66839
66840
66841     contains: function(node) {
66842         return this.nodes.indexOf(node) >= 0;
66843     },
66844
66845
66846     affix: function(node) {
66847         if (this.nodes[0] === node) return 'prefix';
66848         if (this.nodes[this.nodes.length - 1] === node) return 'suffix';
66849     },
66850
66851
66852     layer: function() {
66853         // explicit layer tag, clamp between -10, 10..
66854         if (isFinite(this.tags.layer)) {
66855             return Math.max(-10, Math.min(+(this.tags.layer), 10));
66856         }
66857
66858         // implied layer tag..
66859         if (this.tags.location === 'overground') return 1;
66860         if (this.tags.location === 'underground') return -1;
66861         if (this.tags.location === 'underwater') return -10;
66862
66863         if (this.tags.power === 'line') return 10;
66864         if (this.tags.power === 'minor_line') return 10;
66865         if (this.tags.aerialway) return 10;
66866         if (this.tags.bridge) return 1;
66867         if (this.tags.cutting) return -1;
66868         if (this.tags.tunnel) return -1;
66869         if (this.tags.waterway) return -1;
66870         if (this.tags.man_made === 'pipeline') return -10;
66871         if (this.tags.boundary) return -10;
66872         return 0;
66873     },
66874
66875
66876     isOneWay: function() {
66877         // explicit oneway tag..
66878         if (['yes', '1', '-1'].indexOf(this.tags.oneway) !== -1) { return true; }
66879         if (['no', '0'].indexOf(this.tags.oneway) !== -1) { return false; }
66880
66881         // implied oneway tag..
66882         for (var key in this.tags) {
66883             if (key in osmOneWayTags && (this.tags[key] in osmOneWayTags[key]))
66884                 return true;
66885         }
66886         return false;
66887     },
66888
66889
66890     lanes: function() {
66891         return osmLanes(this);
66892     },
66893
66894
66895     isClosed: function() {
66896         return this.nodes.length > 0 && this.first() === this.last();
66897     },
66898
66899
66900     isConvex: function(resolver) {
66901         if (!this.isClosed() || this.isDegenerate()) return null;
66902
66903         var nodes = lodash.uniq(resolver.childNodes(this)),
66904             coords = lodash.map(nodes, 'loc'),
66905             curr = 0, prev = 0;
66906
66907         for (var i = 0; i < coords.length; i++) {
66908             var o = coords[(i+1) % coords.length],
66909                 a = coords[i],
66910                 b = coords[(i+2) % coords.length],
66911                 res = geoCross(o, a, b);
66912
66913             curr = (res > 0) ? 1 : (res < 0) ? -1 : 0;
66914             if (curr === 0) {
66915                 continue;
66916             } else if (prev && curr !== prev) {
66917                 return false;
66918             }
66919             prev = curr;
66920         }
66921         return true;
66922     },
66923
66924
66925     isArea: function() {
66926         if (this.tags.area === 'yes')
66927             return true;
66928         if (!this.isClosed() || this.tags.area === 'no')
66929             return false;
66930         for (var key in this.tags) {
66931             if (key in areaKeys && !(this.tags[key] in areaKeys[key])) {
66932                 return true;
66933             }
66934         }
66935         return false;
66936     },
66937
66938
66939     isDegenerate: function() {
66940         return lodash.uniq(this.nodes).length < (this.isArea() ? 3 : 2);
66941     },
66942
66943
66944     areAdjacent: function(n1, n2) {
66945         for (var i = 0; i < this.nodes.length; i++) {
66946             if (this.nodes[i] === n1) {
66947                 if (this.nodes[i - 1] === n2) return true;
66948                 if (this.nodes[i + 1] === n2) return true;
66949             }
66950         }
66951         return false;
66952     },
66953
66954
66955     geometry: function(graph) {
66956         return graph.transient(this, 'geometry', function() {
66957             return this.isArea() ? 'area' : 'line';
66958         });
66959     },
66960
66961
66962     addNode: function(id, index) {
66963         var nodes = this.nodes.slice();
66964         nodes.splice(index === undefined ? nodes.length : index, 0, id);
66965         return this.update({nodes: nodes});
66966     },
66967
66968
66969     updateNode: function(id, index) {
66970         var nodes = this.nodes.slice();
66971         nodes.splice(index, 1, id);
66972         return this.update({nodes: nodes});
66973     },
66974
66975
66976     replaceNode: function(needle, replacement) {
66977         if (this.nodes.indexOf(needle) < 0)
66978             return this;
66979
66980         var nodes = this.nodes.slice();
66981         for (var i = 0; i < nodes.length; i++) {
66982             if (nodes[i] === needle) {
66983                 nodes[i] = replacement;
66984             }
66985         }
66986         return this.update({nodes: nodes});
66987     },
66988
66989
66990     removeNode: function(id) {
66991         var nodes = [];
66992
66993         for (var i = 0; i < this.nodes.length; i++) {
66994             var node = this.nodes[i];
66995             if (node !== id && nodes[nodes.length - 1] !== node) {
66996                 nodes.push(node);
66997             }
66998         }
66999
67000         // Preserve circularity
67001         if (this.nodes.length > 1 && this.first() === id && this.last() === id && nodes[nodes.length - 1] !== nodes[0]) {
67002             nodes.push(nodes[0]);
67003         }
67004
67005         return this.update({nodes: nodes});
67006     },
67007
67008
67009     asJXON: function(changeset_id) {
67010         var r = {
67011             way: {
67012                 '@id': this.osmId(),
67013                 '@version': this.version || 0,
67014                 nd: lodash.map(this.nodes, function(id) {
67015                     return { keyAttributes: { ref: osmEntity$$1.id.toOSM(id) } };
67016                 }),
67017                 tag: lodash.map(this.tags, function(v, k) {
67018                     return { keyAttributes: { k: k, v: v } };
67019                 })
67020             }
67021         };
67022         if (changeset_id) r.way['@changeset'] = changeset_id;
67023         return r;
67024     },
67025
67026
67027     asGeoJSON: function(resolver) {
67028         return resolver.transient(this, 'GeoJSON', function() {
67029             var coordinates = lodash.map(resolver.childNodes(this), 'loc');
67030             if (this.isArea() && this.isClosed()) {
67031                 return {
67032                     type: 'Polygon',
67033                     coordinates: [coordinates]
67034                 };
67035             } else {
67036                 return {
67037                     type: 'LineString',
67038                     coordinates: coordinates
67039                 };
67040             }
67041         });
67042     },
67043
67044
67045     area: function(resolver) {
67046         return resolver.transient(this, 'area', function() {
67047             var nodes = resolver.childNodes(this);
67048
67049             var json$$1 = {
67050                 type: 'Polygon',
67051                 coordinates: [lodash.map(nodes, 'loc')]
67052             };
67053
67054             if (!this.isClosed() && nodes.length) {
67055                 json$$1.coordinates[0].push(nodes[0].loc);
67056             }
67057
67058             var area$$1 = area$1(json$$1);
67059
67060             // Heuristic for detecting counterclockwise winding order. Assumes
67061             // that OpenStreetMap polygons are not hemisphere-spanning.
67062             if (area$$1 > 2 * Math.PI) {
67063                 json$$1.coordinates[0] = json$$1.coordinates[0].reverse();
67064                 area$$1 = area$1(json$$1);
67065             }
67066
67067             return isNaN(area$$1) ? 0 : area$$1;
67068         });
67069     }
67070 });
67071
67072 function osmTurn(turn) {
67073     if (!(this instanceof osmTurn))
67074         return new osmTurn(turn);
67075     lodash.extend(this, turn);
67076 }
67077
67078
67079 function osmIntersection(graph, vertexId) {
67080     var vertex = graph.entity(vertexId),
67081         parentWays = graph.parentWays(vertex),
67082         coincident = [],
67083         highways = {};
67084
67085     function addHighway(way, adjacentNodeId) {
67086         if (highways[adjacentNodeId]) {
67087             coincident.push(adjacentNodeId);
67088         } else {
67089             highways[adjacentNodeId] = way;
67090         }
67091     }
67092
67093     // Pre-split ways that would need to be split in
67094     // order to add a restriction. The real split will
67095     // happen when the restriction is added.
67096     parentWays.forEach(function(way) {
67097         if (!way.tags.highway || way.isArea() || way.isDegenerate())
67098             return;
67099
67100         var isFirst = (vertexId === way.first()),
67101             isLast = (vertexId === way.last()),
67102             isAffix = (isFirst || isLast),
67103             isClosingNode = (isFirst && isLast);
67104
67105         if (isAffix && !isClosingNode) {
67106             var index = (isFirst ? 1 : way.nodes.length - 2);
67107             addHighway(way, way.nodes[index]);
67108
67109         } else {
67110             var splitIndex, wayA, wayB, indexA, indexB;
67111             if (isClosingNode) {
67112                 splitIndex = Math.ceil(way.nodes.length / 2);  // split at midpoint
67113                 wayA = osmWay({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex)});
67114                 wayB = osmWay({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
67115                 indexA = 1;
67116                 indexB = way.nodes.length - 2;
67117             } else {
67118                 splitIndex = lodash.indexOf(way.nodes, vertex.id, 1);  // split at vertexid
67119                 wayA = osmWay({id: way.id + '-a', tags: way.tags, nodes: way.nodes.slice(0, splitIndex + 1)});
67120                 wayB = osmWay({id: way.id + '-b', tags: way.tags, nodes: way.nodes.slice(splitIndex)});
67121                 indexA = splitIndex - 1;
67122                 indexB = splitIndex + 1;
67123             }
67124             graph = graph.replace(wayA).replace(wayB);
67125             addHighway(wayA, way.nodes[indexA]);
67126             addHighway(wayB, way.nodes[indexB]);
67127         }
67128     });
67129
67130     // remove any ways from this intersection that are coincident
67131     // (i.e. any adjacent node used by more than one intersecting way)
67132     coincident.forEach(function (n) {
67133         delete highways[n];
67134     });
67135
67136
67137     var intersection = {
67138         highways: highways,
67139         ways: lodash.values(highways),
67140         graph: graph
67141     };
67142
67143
67144     intersection.adjacentNodeId = function(fromWayId) {
67145         return lodash.find(lodash.keys(highways), function(k) {
67146             return highways[k].id === fromWayId;
67147         });
67148     };
67149
67150
67151     intersection.turns = function(fromNodeId) {
67152         var start = highways[fromNodeId];
67153         if (!start)
67154             return [];
67155
67156         if (start.first() === vertex.id && start.tags.oneway === 'yes')
67157             return [];
67158         if (start.last() === vertex.id && start.tags.oneway === '-1')
67159             return [];
67160
67161         function withRestriction(turn) {
67162             graph.parentRelations(graph.entity(turn.from.way)).forEach(function(relation) {
67163                 if (relation.tags.type !== 'restriction')
67164                     return;
67165
67166                 var f = relation.memberByRole('from'),
67167                     t = relation.memberByRole('to'),
67168                     v = relation.memberByRole('via');
67169
67170                 if (f && f.id === turn.from.way &&
67171                     v && v.id === turn.via.node &&
67172                     t && t.id === turn.to.way) {
67173                     turn.restriction = relation.id;
67174                 } else if (/^only_/.test(relation.tags.restriction) &&
67175                     f && f.id === turn.from.way &&
67176                     v && v.id === turn.via.node &&
67177                     t && t.id !== turn.to.way) {
67178                     turn.restriction = relation.id;
67179                     turn.indirect_restriction = true;
67180                 }
67181             });
67182
67183             return osmTurn(turn);
67184         }
67185
67186
67187         var from = {
67188                 node: fromNodeId,
67189                 way: start.id.split(/-(a|b)/)[0]
67190             },
67191             via = { node: vertex.id },
67192             turns = [];
67193
67194         lodash.each(highways, function(end, adjacentNodeId) {
67195             if (end === start)
67196                 return;
67197
67198             // backward
67199             if (end.first() !== vertex.id && end.tags.oneway !== 'yes') {
67200                 turns.push(withRestriction({
67201                     from: from,
67202                     via: via,
67203                     to: {
67204                         node: adjacentNodeId,
67205                         way: end.id.split(/-(a|b)/)[0]
67206                     }
67207                 }));
67208             }
67209
67210             // forward
67211             if (end.last() !== vertex.id && end.tags.oneway !== '-1') {
67212                 turns.push(withRestriction({
67213                     from: from,
67214                     via: via,
67215                     to: {
67216                         node: adjacentNodeId,
67217                         way: end.id.split(/-(a|b)/)[0]
67218                     }
67219                 }));
67220             }
67221
67222         });
67223
67224         // U-turn
67225         if (start.tags.oneway !== 'yes' && start.tags.oneway !== '-1') {
67226             turns.push(withRestriction({
67227                 from: from,
67228                 via: via,
67229                 to: from,
67230                 u: true
67231             }));
67232         }
67233
67234         return turns;
67235     };
67236
67237     return intersection;
67238 }
67239
67240
67241 function osmInferRestriction(graph, from, via, to, projection) {
67242     var fromWay = graph.entity(from.way),
67243         fromNode = graph.entity(from.node),
67244         toWay = graph.entity(to.way),
67245         toNode = graph.entity(to.node),
67246         viaNode = graph.entity(via.node),
67247         fromOneWay = (fromWay.tags.oneway === 'yes' && fromWay.last() === via.node) ||
67248             (fromWay.tags.oneway === '-1' && fromWay.first() === via.node),
67249         toOneWay = (toWay.tags.oneway === 'yes' && toWay.first() === via.node) ||
67250             (toWay.tags.oneway === '-1' && toWay.last() === via.node),
67251         angle = geoAngle(viaNode, fromNode, projection) -
67252                 geoAngle(viaNode, toNode, projection);
67253
67254     angle = angle * 180 / Math.PI;
67255
67256     while (angle < 0)
67257         angle += 360;
67258
67259     if (fromNode === toNode)
67260         return 'no_u_turn';
67261     if ((angle < 23 || angle > 336) && fromOneWay && toOneWay)
67262         return 'no_u_turn';
67263     if (angle < 158)
67264         return 'no_right_turn';
67265     if (angle > 202)
67266         return 'no_left_turn';
67267
67268     return 'no_straight_on';
67269 }
67270
67271 function actionAddMember(relationId, member, memberIndex) {
67272     return function(graph) {
67273         var relation = graph.entity(relationId);
67274
67275         if (isNaN(memberIndex) && member.type === 'way') {
67276             var members = relation.indexedMembers();
67277             members.push(member);
67278
67279             var joined = osmJoinWays(members, graph);
67280             for (var i = 0; i < joined.length; i++) {
67281                 var segment = joined[i];
67282                 for (var j = 0; j < segment.length && segment.length >= 2; j++) {
67283                     if (segment[j] !== member)
67284                         continue;
67285
67286                     if (j === 0) {
67287                         memberIndex = segment[j + 1].index;
67288                     } else if (j === segment.length - 1) {
67289                         memberIndex = segment[j - 1].index + 1;
67290                     } else {
67291                         memberIndex = Math.min(segment[j - 1].index + 1, segment[j + 1].index + 1);
67292                     }
67293                 }
67294             }
67295         }
67296
67297         return graph.replace(relation.addMember(member, memberIndex));
67298     };
67299 }
67300
67301 function actionAddMidpoint(midpoint, node) {
67302     return function(graph) {
67303         graph = graph.replace(node.move(midpoint.loc));
67304
67305         var parents = lodash.intersection(
67306             graph.parentWays(graph.entity(midpoint.edge[0])),
67307             graph.parentWays(graph.entity(midpoint.edge[1])));
67308
67309         parents.forEach(function(way) {
67310             for (var i = 0; i < way.nodes.length - 1; i++) {
67311                 if (geoEdgeEqual([way.nodes[i], way.nodes[i + 1]], midpoint.edge)) {
67312                     graph = graph.replace(graph.entity(way.id).addNode(node.id, i + 1));
67313
67314                     // Add only one midpoint on doubled-back segments,
67315                     // turning them into self-intersections.
67316                     return;
67317                 }
67318             }
67319         });
67320
67321         return graph;
67322     };
67323 }
67324
67325 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/AddNodeToWayAction.as
67326 function actionAddVertex(wayId, nodeId, index) {
67327     return function(graph) {
67328         return graph.replace(graph.entity(wayId).addNode(nodeId, index));
67329     };
67330 }
67331
67332 function actionChangeMember(relationId, member, memberIndex) {
67333     return function(graph) {
67334         return graph.replace(graph.entity(relationId).updateMember(member, memberIndex));
67335     };
67336 }
67337
67338 function actionChangePreset(entityId, oldPreset, newPreset) {
67339     return function(graph) {
67340         var entity = graph.entity(entityId),
67341             geometry = entity.geometry(graph),
67342             tags = entity.tags;
67343
67344         if (oldPreset) tags = oldPreset.removeTags(tags, geometry);
67345         if (newPreset) tags = newPreset.applyTags(tags, geometry);
67346
67347         return graph.replace(entity.update({tags: tags}));
67348     };
67349 }
67350
67351 function actionChangeTags(entityId, tags) {
67352     return function(graph) {
67353         var entity = graph.entity(entityId);
67354         return graph.replace(entity.update({tags: tags}));
67355     };
67356 }
67357
67358 function actionCircularize(wayId, projection, maxAngle) {
67359     maxAngle = (maxAngle || 20) * Math.PI / 180;
67360
67361
67362     var action = function(graph) {
67363         var way = graph.entity(wayId);
67364
67365         if (!way.isConvex(graph)) {
67366             graph = action.makeConvex(graph);
67367         }
67368
67369         var nodes = lodash.uniq(graph.childNodes(way)),
67370             keyNodes = nodes.filter(function(n) { return graph.parentWays(n).length !== 1; }),
67371             points = nodes.map(function(n) { return projection(n.loc); }),
67372             keyPoints = keyNodes.map(function(n) { return projection(n.loc); }),
67373             centroid = (points.length === 2) ? geoInterp(points[0], points[1], 0.5) : d3polygonCentroid(points),
67374             radius = median(points, function(p) { return geoEuclideanDistance(centroid, p); }),
67375             sign = d3polygonArea(points) > 0 ? 1 : -1,
67376             ids;
67377
67378         // we need atleast two key nodes for the algorithm to work
67379         if (!keyNodes.length) {
67380             keyNodes = [nodes[0]];
67381             keyPoints = [points[0]];
67382         }
67383
67384         if (keyNodes.length === 1) {
67385             var index = nodes.indexOf(keyNodes[0]),
67386                 oppositeIndex = Math.floor((index + nodes.length / 2) % nodes.length);
67387
67388             keyNodes.push(nodes[oppositeIndex]);
67389             keyPoints.push(points[oppositeIndex]);
67390         }
67391
67392         // key points and nodes are those connected to the ways,
67393         // they are projected onto the circle, inbetween nodes are moved
67394         // to constant intervals between key nodes, extra inbetween nodes are
67395         // added if necessary.
67396         for (var i = 0; i < keyPoints.length; i++) {
67397             var nextKeyNodeIndex = (i + 1) % keyNodes.length,
67398                 startNode = keyNodes[i],
67399                 endNode = keyNodes[nextKeyNodeIndex],
67400                 startNodeIndex = nodes.indexOf(startNode),
67401                 endNodeIndex = nodes.indexOf(endNode),
67402                 numberNewPoints = -1,
67403                 indexRange = endNodeIndex - startNodeIndex,
67404                 distance, totalAngle, eachAngle, startAngle, endAngle,
67405                 angle, loc, node, j,
67406                 inBetweenNodes = [];
67407
67408             if (indexRange < 0) {
67409                 indexRange += nodes.length;
67410             }
67411
67412             // position this key node
67413             distance = geoEuclideanDistance(centroid, keyPoints[i]);
67414             if (distance === 0) { distance = 1e-4; }
67415             keyPoints[i] = [
67416                 centroid[0] + (keyPoints[i][0] - centroid[0]) / distance * radius,
67417                 centroid[1] + (keyPoints[i][1] - centroid[1]) / distance * radius];
67418             graph = graph.replace(keyNodes[i].move(projection.invert(keyPoints[i])));
67419
67420             // figure out the between delta angle we want to match to
67421             startAngle = Math.atan2(keyPoints[i][1] - centroid[1], keyPoints[i][0] - centroid[0]);
67422             endAngle = Math.atan2(keyPoints[nextKeyNodeIndex][1] - centroid[1], keyPoints[nextKeyNodeIndex][0] - centroid[0]);
67423             totalAngle = endAngle - startAngle;
67424
67425             // detects looping around -pi/pi
67426             if (totalAngle * sign > 0) {
67427                 totalAngle = -sign * (2 * Math.PI - Math.abs(totalAngle));
67428             }
67429
67430             do {
67431                 numberNewPoints++;
67432                 eachAngle = totalAngle / (indexRange + numberNewPoints);
67433             } while (Math.abs(eachAngle) > maxAngle);
67434
67435             // move existing points
67436             for (j = 1; j < indexRange; j++) {
67437                 angle = startAngle + j * eachAngle;
67438                 loc = projection.invert([
67439                     centroid[0] + Math.cos(angle)*radius,
67440                     centroid[1] + Math.sin(angle)*radius]);
67441
67442                 node = nodes[(j + startNodeIndex) % nodes.length].move(loc);
67443                 graph = graph.replace(node);
67444             }
67445
67446             // add new inbetween nodes if necessary
67447             for (j = 0; j < numberNewPoints; j++) {
67448                 angle = startAngle + (indexRange + j) * eachAngle;
67449                 loc = projection.invert([
67450                     centroid[0] + Math.cos(angle) * radius,
67451                     centroid[1] + Math.sin(angle) * radius]);
67452
67453                 node = osmNode({loc: loc});
67454                 graph = graph.replace(node);
67455
67456                 nodes.splice(endNodeIndex + j, 0, node);
67457                 inBetweenNodes.push(node.id);
67458             }
67459
67460             // Check for other ways that share these keyNodes..
67461             // If keyNodes are adjacent in both ways,
67462             // we can add inBetween nodes to that shared way too..
67463             if (indexRange === 1 && inBetweenNodes.length) {
67464                 var startIndex1 = way.nodes.lastIndexOf(startNode.id),
67465                     endIndex1 = way.nodes.lastIndexOf(endNode.id),
67466                     wayDirection1 = (endIndex1 - startIndex1);
67467                 if (wayDirection1 < -1) { wayDirection1 = 1; }
67468
67469                 /* eslint-disable no-loop-func */
67470                 lodash.each(lodash.without(graph.parentWays(keyNodes[i]), way), function(sharedWay) {
67471                     if (sharedWay.areAdjacent(startNode.id, endNode.id)) {
67472                         var startIndex2 = sharedWay.nodes.lastIndexOf(startNode.id),
67473                             endIndex2 = sharedWay.nodes.lastIndexOf(endNode.id),
67474                             wayDirection2 = (endIndex2 - startIndex2),
67475                             insertAt = endIndex2;
67476                         if (wayDirection2 < -1) { wayDirection2 = 1; }
67477
67478                         if (wayDirection1 !== wayDirection2) {
67479                             inBetweenNodes.reverse();
67480                             insertAt = startIndex2;
67481                         }
67482                         for (j = 0; j < inBetweenNodes.length; j++) {
67483                             sharedWay = sharedWay.addNode(inBetweenNodes[j], insertAt + j);
67484                         }
67485                         graph = graph.replace(sharedWay);
67486                     }
67487                 });
67488                 /* eslint-enable no-loop-func */
67489             }
67490
67491         }
67492
67493         // update the way to have all the new nodes
67494         ids = nodes.map(function(n) { return n.id; });
67495         ids.push(ids[0]);
67496
67497         way = way.update({nodes: ids});
67498         graph = graph.replace(way);
67499
67500         return graph;
67501     };
67502
67503
67504     action.makeConvex = function(graph) {
67505         var way = graph.entity(wayId),
67506             nodes = lodash.uniq(graph.childNodes(way)),
67507             points = nodes.map(function(n) { return projection(n.loc); }),
67508             sign = d3polygonArea(points) > 0 ? 1 : -1,
67509             hull = d3polygonHull(points);
67510
67511         // D3 convex hulls go counterclockwise..
67512         if (sign === -1) {
67513             nodes.reverse();
67514             points.reverse();
67515         }
67516
67517         for (var i = 0; i < hull.length - 1; i++) {
67518             var startIndex = points.indexOf(hull[i]),
67519                 endIndex = points.indexOf(hull[i+1]),
67520                 indexRange = (endIndex - startIndex);
67521
67522             if (indexRange < 0) {
67523                 indexRange += nodes.length;
67524             }
67525
67526             // move interior nodes to the surface of the convex hull..
67527             for (var j = 1; j < indexRange; j++) {
67528                 var point = geoInterp(hull[i], hull[i+1], j / indexRange),
67529                     node = nodes[(j + startIndex) % nodes.length].move(projection.invert(point));
67530                 graph = graph.replace(node);
67531             }
67532         }
67533         return graph;
67534     };
67535
67536
67537     action.disabled = function(graph) {
67538         if (!graph.entity(wayId).isClosed())
67539             return 'not_closed';
67540     };
67541
67542
67543     return action;
67544 }
67545
67546 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteWayAction.as
67547 function actionDeleteWay(wayId) {
67548
67549
67550     function canDeleteNode(node, graph) {
67551         return !graph.parentWays(node).length &&
67552             !graph.parentRelations(node).length &&
67553             !node.hasInterestingTags();
67554     }
67555
67556
67557     var action = function(graph) {
67558         var way = graph.entity(wayId);
67559
67560         graph.parentRelations(way)
67561             .forEach(function(parent) {
67562                 parent = parent.removeMembersWithID(wayId);
67563                 graph = graph.replace(parent);
67564
67565                 if (parent.isDegenerate()) {
67566                     graph = actionDeleteRelation(parent.id)(graph);
67567                 }
67568             });
67569
67570         lodash.uniq(way.nodes).forEach(function(nodeId) {
67571             graph = graph.replace(way.removeNode(nodeId));
67572
67573             var node = graph.entity(nodeId);
67574             if (canDeleteNode(node, graph)) {
67575                 graph = graph.remove(node);
67576             }
67577         });
67578
67579         return graph.remove(way);
67580     };
67581
67582
67583     action.disabled = function(graph) {
67584         var disabled = false;
67585
67586         graph.parentRelations(graph.entity(wayId)).forEach(function(parent) {
67587             var type = parent.tags.type,
67588                 role = parent.memberById(wayId).role || 'outer';
67589             if (type === 'route' || type === 'boundary' || (type === 'multipolygon' && role === 'outer')) {
67590                 disabled = 'part_of_relation';
67591             }
67592         });
67593
67594         return disabled;
67595     };
67596
67597
67598     return action;
67599 }
67600
67601 function actionDeleteMultiple(ids) {
67602     var actions = {
67603         way: actionDeleteWay,
67604         node: actionDeleteNode,
67605         relation: actionDeleteRelation
67606     };
67607
67608
67609     var action = function(graph) {
67610         ids.forEach(function(id) {
67611             if (graph.hasEntity(id)) { // It may have been deleted aready.
67612                 graph = actions[graph.entity(id).type](id)(graph);
67613             }
67614         });
67615
67616         return graph;
67617     };
67618
67619
67620     action.disabled = function(graph) {
67621         for (var i = 0; i < ids.length; i++) {
67622             var id = ids[i],
67623                 disabled = actions[graph.entity(id).type](id).disabled(graph);
67624             if (disabled) return disabled;
67625         }
67626     };
67627
67628
67629     return action;
67630 }
67631
67632 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteRelationAction.as
67633 function actionDeleteRelation(relationId) {
67634
67635
67636     function canDeleteEntity(entity, graph) {
67637         return !graph.parentWays(entity).length &&
67638             !graph.parentRelations(entity).length &&
67639             !entity.hasInterestingTags();
67640     }
67641
67642
67643     var action = function(graph) {
67644         var relation = graph.entity(relationId);
67645
67646         graph.parentRelations(relation)
67647             .forEach(function(parent) {
67648                 parent = parent.removeMembersWithID(relationId);
67649                 graph = graph.replace(parent);
67650
67651                 if (parent.isDegenerate()) {
67652                     graph = actionDeleteRelation(parent.id)(graph);
67653                 }
67654             });
67655
67656         lodash.uniq(lodash.map(relation.members, 'id')).forEach(function(memberId) {
67657             graph = graph.replace(relation.removeMembersWithID(memberId));
67658
67659             var entity = graph.entity(memberId);
67660             if (canDeleteEntity(entity, graph)) {
67661                 graph = actionDeleteMultiple([memberId])(graph);
67662             }
67663         });
67664
67665         return graph.remove(relation);
67666     };
67667
67668
67669     action.disabled = function(graph) {
67670         if (!graph.entity(relationId).isComplete(graph))
67671             return 'incomplete_relation';
67672     };
67673
67674
67675     return action;
67676 }
67677
67678 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/DeleteNodeAction.as
67679 function actionDeleteNode(nodeId) {
67680     var action = function(graph) {
67681         var node = graph.entity(nodeId);
67682
67683         graph.parentWays(node)
67684             .forEach(function(parent) {
67685                 parent = parent.removeNode(nodeId);
67686                 graph = graph.replace(parent);
67687
67688                 if (parent.isDegenerate()) {
67689                     graph = actionDeleteWay(parent.id)(graph);
67690                 }
67691             });
67692
67693         graph.parentRelations(node)
67694             .forEach(function(parent) {
67695                 parent = parent.removeMembersWithID(nodeId);
67696                 graph = graph.replace(parent);
67697
67698                 if (parent.isDegenerate()) {
67699                     graph = actionDeleteRelation(parent.id)(graph);
67700                 }
67701             });
67702
67703         return graph.remove(node);
67704     };
67705
67706
67707     action.disabled = function() {
67708         return false;
67709     };
67710
67711
67712     return action;
67713 }
67714
67715 // Connect the ways at the given nodes.
67716 //
67717 // The last node will survive. All other nodes will be replaced with
67718 // the surviving node in parent ways, and then removed.
67719 //
67720 // Tags and relation memberships of of non-surviving nodes are merged
67721 // to the survivor.
67722 //
67723 // This is the inverse of `iD.actionDisconnect`.
67724 //
67725 // Reference:
67726 //   https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeNodesAction.as
67727 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/MergeNodesAction.java
67728 //
67729 function actionConnect(nodeIds) {
67730     return function(graph) {
67731         var survivor = graph.entity(lodash.last(nodeIds));
67732
67733         for (var i = 0; i < nodeIds.length - 1; i++) {
67734             var node = graph.entity(nodeIds[i]);
67735
67736             /* eslint-disable no-loop-func */
67737             graph.parentWays(node).forEach(function(parent) {
67738                 if (!parent.areAdjacent(node.id, survivor.id)) {
67739                     graph = graph.replace(parent.replaceNode(node.id, survivor.id));
67740                 }
67741             });
67742
67743             graph.parentRelations(node).forEach(function(parent) {
67744                 graph = graph.replace(parent.replaceMember(node, survivor));
67745             });
67746             /* eslint-enable no-loop-func */
67747
67748             survivor = survivor.mergeTags(node.tags);
67749             graph = actionDeleteNode(node.id)(graph);
67750         }
67751
67752         graph = graph.replace(survivor);
67753
67754         return graph;
67755     };
67756 }
67757
67758 function actionCopyEntities(ids, fromGraph) {
67759     var copies = {};
67760
67761
67762     var action = function(graph) {
67763         ids.forEach(function(id) {
67764             fromGraph.entity(id).copy(fromGraph, copies);
67765         });
67766
67767         for (var id in copies) {
67768             graph = graph.replace(copies[id]);
67769         }
67770
67771         return graph;
67772     };
67773
67774
67775     action.copies = function() {
67776         return copies;
67777     };
67778
67779
67780     return action;
67781 }
67782
67783 function actionDeleteMember(relationId, memberIndex) {
67784     return function(graph) {
67785         var relation = graph.entity(relationId)
67786             .removeMember(memberIndex);
67787
67788         graph = graph.replace(relation);
67789
67790         if (relation.isDegenerate())
67791             graph = actionDeleteRelation(relation.id)(graph);
67792
67793         return graph;
67794     };
67795 }
67796
67797 function actionDeprecateTags(entityId) {
67798
67799     return function(graph) {
67800         var entity = graph.entity(entityId),
67801             newtags = lodash.clone(entity.tags),
67802             change = false,
67803             rule;
67804
67805         // This handles dataDeprecated tags with a single condition
67806         for (var i = 0; i < dataDeprecated.length; i++) {
67807
67808             rule = dataDeprecated[i];
67809             var match = lodash.toPairs(rule.old)[0],
67810                 replacements = rule.replace ? lodash.toPairs(rule.replace) : null;
67811
67812             if (entity.tags[match[0]] && match[1] === '*') {
67813
67814                 var value = entity.tags[match[0]];
67815                 if (replacements && !newtags[replacements[0][0]]) {
67816                     newtags[replacements[0][0]] = value;
67817                 }
67818                 delete newtags[match[0]];
67819                 change = true;
67820
67821             } else if (entity.tags[match[0]] === match[1]) {
67822                 newtags = lodash.assign({}, rule.replace || {}, lodash.omit(newtags, match[0]));
67823                 change = true;
67824             }
67825         }
67826
67827         if (change) {
67828             return graph.replace(entity.update({tags: newtags}));
67829         } else {
67830             return graph;
67831         }
67832     };
67833 }
67834
67835 function actionDiscardTags(difference) {
67836
67837     return function(graph) {
67838         function discardTags(entity) {
67839             if (!lodash.isEmpty(entity.tags)) {
67840                 var tags = {};
67841                 lodash.each(entity.tags, function(v, k) {
67842                     if (v) tags[k] = v;
67843                 });
67844
67845                 graph = graph.replace(entity.update({
67846                     tags: lodash.omit(tags, dataDiscarded)
67847                 }));
67848             }
67849         }
67850
67851         difference.modified().forEach(discardTags);
67852         difference.created().forEach(discardTags);
67853
67854         return graph;
67855     };
67856 }
67857
67858 // Disconect the ways at the given node.
67859 //
67860 // Optionally, disconnect only the given ways.
67861 //
67862 // For testing convenience, accepts an ID to assign to the (first) new node.
67863 // Normally, this will be undefined and the way will automatically
67864 // be assigned a new ID.
67865 //
67866 // This is the inverse of `iD.actionConnect`.
67867 //
67868 // Reference:
67869 //   https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/UnjoinNodeAction.as
67870 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/UnGlueAction.java
67871 //
67872 function actionDisconnect(nodeId, newNodeId) {
67873     var wayIds;
67874
67875
67876     var action = function(graph) {
67877         var node = graph.entity(nodeId),
67878             connections = action.connections(graph);
67879
67880         connections.forEach(function(connection) {
67881             var way = graph.entity(connection.wayID),
67882                 newNode = osmNode({id: newNodeId, loc: node.loc, tags: node.tags});
67883
67884             graph = graph.replace(newNode);
67885             if (connection.index === 0 && way.isArea()) {
67886                 // replace shared node with shared node..
67887                 graph = graph.replace(way.replaceNode(way.nodes[0], newNode.id));
67888             } else {
67889                 // replace shared node with multiple new nodes..
67890                 graph = graph.replace(way.updateNode(newNode.id, connection.index));
67891             }
67892         });
67893
67894         return graph;
67895     };
67896
67897
67898     action.connections = function(graph) {
67899         var candidates = [],
67900             keeping = false,
67901             parentWays = graph.parentWays(graph.entity(nodeId));
67902
67903         parentWays.forEach(function(way) {
67904             if (wayIds && wayIds.indexOf(way.id) === -1) {
67905                 keeping = true;
67906                 return;
67907             }
67908             if (way.isArea() && (way.nodes[0] === nodeId)) {
67909                 candidates.push({wayID: way.id, index: 0});
67910             } else {
67911                 way.nodes.forEach(function(waynode, index) {
67912                     if (waynode === nodeId) {
67913                         candidates.push({wayID: way.id, index: index});
67914                     }
67915                 });
67916             }
67917         });
67918
67919         return keeping ? candidates : candidates.slice(1);
67920     };
67921
67922
67923     action.disabled = function(graph) {
67924         var connections = action.connections(graph);
67925         if (connections.length === 0 || (wayIds && wayIds.length !== connections.length))
67926             return 'not_connected';
67927
67928         var parentWays = graph.parentWays(graph.entity(nodeId)),
67929             seenRelationIds = {},
67930             sharedRelation;
67931
67932         parentWays.forEach(function(way) {
67933             if (wayIds && wayIds.indexOf(way.id) === -1)
67934                 return;
67935
67936             var relations = graph.parentRelations(way);
67937             relations.forEach(function(relation) {
67938                 if (relation.id in seenRelationIds) {
67939                     sharedRelation = relation;
67940                 } else {
67941                     seenRelationIds[relation.id] = true;
67942                 }
67943             });
67944         });
67945
67946         if (sharedRelation)
67947             return 'relation';
67948     };
67949
67950
67951     action.limitWays = function(_) {
67952         if (!arguments.length) return wayIds;
67953         wayIds = _;
67954         return action;
67955     };
67956
67957
67958     return action;
67959 }
67960
67961 // Join ways at the end node they share.
67962 //
67963 // This is the inverse of `iD.actionSplit`.
67964 //
67965 // Reference:
67966 //   https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MergeWaysAction.as
67967 //   https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/actions/CombineWayAction.java
67968 //
67969 function actionJoin(ids) {
67970
67971     function groupEntitiesByGeometry(graph) {
67972         var entities = ids.map(function(id) { return graph.entity(id); });
67973         return lodash.extend({line: []}, lodash.groupBy(entities, function(entity) { return entity.geometry(graph); }));
67974     }
67975
67976
67977     var action = function(graph) {
67978         var ways = ids.map(graph.entity, graph),
67979             survivor = ways[0];
67980
67981         // Prefer to keep an existing way.
67982         for (var i = 0; i < ways.length; i++) {
67983             if (!ways[i].isNew()) {
67984                 survivor = ways[i];
67985                 break;
67986             }
67987         }
67988
67989         var joined = osmJoinWays(ways, graph)[0];
67990
67991         survivor = survivor.update({nodes: lodash.map(joined.nodes, 'id')});
67992         graph = graph.replace(survivor);
67993
67994         joined.forEach(function(way) {
67995             if (way.id === survivor.id)
67996                 return;
67997
67998             graph.parentRelations(way).forEach(function(parent) {
67999                 graph = graph.replace(parent.replaceMember(way, survivor));
68000             });
68001
68002             survivor = survivor.mergeTags(way.tags);
68003
68004             graph = graph.replace(survivor);
68005             graph = actionDeleteWay(way.id)(graph);
68006         });
68007
68008         return graph;
68009     };
68010
68011
68012     action.disabled = function(graph) {
68013         var geometries = groupEntitiesByGeometry(graph);
68014         if (ids.length < 2 || ids.length !== geometries.line.length)
68015             return 'not_eligible';
68016
68017         var joined = osmJoinWays(ids.map(graph.entity, graph), graph);
68018         if (joined.length > 1)
68019             return 'not_adjacent';
68020
68021         var nodeIds = lodash.map(joined[0].nodes, 'id').slice(1, -1),
68022             relation,
68023             tags = {},
68024             conflicting = false;
68025
68026         joined[0].forEach(function(way) {
68027             var parents = graph.parentRelations(way);
68028             parents.forEach(function(parent) {
68029                 if (parent.isRestriction() && parent.members.some(function(m) { return nodeIds.indexOf(m.id) >= 0; }))
68030                     relation = parent;
68031             });
68032
68033             for (var k in way.tags) {
68034                 if (!(k in tags)) {
68035                     tags[k] = way.tags[k];
68036                 } else if (tags[k] && osmIsInterestingTag(k) && tags[k] !== way.tags[k]) {
68037                     conflicting = true;
68038                 }
68039             }
68040         });
68041
68042         if (relation)
68043             return 'restriction';
68044
68045         if (conflicting)
68046             return 'conflicting_tags';
68047     };
68048
68049
68050     return action;
68051 }
68052
68053 function actionMerge(ids) {
68054
68055     function groupEntitiesByGeometry(graph) {
68056         var entities = ids.map(function(id) { return graph.entity(id); });
68057         return lodash.extend({point: [], area: [], line: [], relation: []},
68058             lodash.groupBy(entities, function(entity) { return entity.geometry(graph); }));
68059     }
68060
68061
68062     var action = function(graph) {
68063         var geometries = groupEntitiesByGeometry(graph),
68064             target = geometries.area[0] || geometries.line[0],
68065             points = geometries.point;
68066
68067         points.forEach(function(point) {
68068             target = target.mergeTags(point.tags);
68069
68070             graph.parentRelations(point).forEach(function(parent) {
68071                 graph = graph.replace(parent.replaceMember(point, target));
68072             });
68073
68074             graph = graph.remove(point);
68075         });
68076
68077         graph = graph.replace(target);
68078
68079         return graph;
68080     };
68081
68082
68083     action.disabled = function(graph) {
68084         var geometries = groupEntitiesByGeometry(graph);
68085         if (geometries.point.length === 0 ||
68086             (geometries.area.length + geometries.line.length) !== 1 ||
68087             geometries.relation.length !== 0)
68088             return 'not_eligible';
68089     };
68090
68091
68092     return action;
68093 }
68094
68095 function actionMergePolygon(ids, newRelationId) {
68096
68097     function groupEntities(graph) {
68098         var entities = ids.map(function (id) { return graph.entity(id); });
68099         return lodash.extend({
68100                 closedWay: [],
68101                 multipolygon: [],
68102                 other: []
68103             }, lodash.groupBy(entities, function(entity) {
68104                 if (entity.type === 'way' && entity.isClosed()) {
68105                     return 'closedWay';
68106                 } else if (entity.type === 'relation' && entity.isMultipolygon()) {
68107                     return 'multipolygon';
68108                 } else {
68109                     return 'other';
68110                 }
68111             }));
68112     }
68113
68114
68115     var action = function(graph) {
68116         var entities = groupEntities(graph);
68117
68118         // An array representing all the polygons that are part of the multipolygon.
68119         //
68120         // Each element is itself an array of objects with an id property, and has a
68121         // locs property which is an array of the locations forming the polygon.
68122         var polygons = entities.multipolygon.reduce(function(polygons, m) {
68123             return polygons.concat(osmJoinWays(m.members, graph));
68124         }, []).concat(entities.closedWay.map(function(d) {
68125             var member = [{id: d.id}];
68126             member.nodes = graph.childNodes(d);
68127             return member;
68128         }));
68129
68130         // contained is an array of arrays of boolean values,
68131         // where contained[j][k] is true iff the jth way is
68132         // contained by the kth way.
68133         var contained = polygons.map(function(w, i) {
68134             return polygons.map(function(d, n) {
68135                 if (i === n) return null;
68136                 return geoPolygonContainsPolygon(
68137                     lodash.map(d.nodes, 'loc'),
68138                     lodash.map(w.nodes, 'loc'));
68139             });
68140         });
68141
68142         // Sort all polygons as either outer or inner ways
68143         var members = [],
68144             outer = true;
68145
68146         while (polygons.length) {
68147             extractUncontained(polygons);
68148             polygons = polygons.filter(isContained);
68149             contained = contained.filter(isContained).map(filterContained);
68150         }
68151
68152         function isContained(d, i) {
68153             return lodash.some(contained[i]);
68154         }
68155
68156         function filterContained(d) {
68157             return d.filter(isContained);
68158         }
68159
68160         function extractUncontained(polygons) {
68161             polygons.forEach(function(d, i) {
68162                 if (!isContained(d, i)) {
68163                     d.forEach(function(member) {
68164                         members.push({
68165                             type: 'way',
68166                             id: member.id,
68167                             role: outer ? 'outer' : 'inner'
68168                         });
68169                     });
68170                 }
68171             });
68172             outer = !outer;
68173         }
68174
68175         // Move all tags to one relation
68176         var relation = entities.multipolygon[0] ||
68177             osmRelation({ id: newRelationId, tags: { type: 'multipolygon' }});
68178
68179         entities.multipolygon.slice(1).forEach(function(m) {
68180             relation = relation.mergeTags(m.tags);
68181             graph = graph.remove(m);
68182         });
68183
68184         entities.closedWay.forEach(function(way) {
68185             function isThisOuter(m) {
68186                 return m.id === way.id && m.role !== 'inner';
68187             }
68188             if (members.some(isThisOuter)) {
68189                 relation = relation.mergeTags(way.tags);
68190                 graph = graph.replace(way.update({ tags: {} }));
68191             }
68192         });
68193
68194         return graph.replace(relation.update({
68195             members: members,
68196             tags: lodash.omit(relation.tags, 'area')
68197         }));
68198     };
68199
68200
68201     action.disabled = function(graph) {
68202         var entities = groupEntities(graph);
68203         if (entities.other.length > 0 ||
68204             entities.closedWay.length + entities.multipolygon.length < 2)
68205             return 'not_eligible';
68206         if (!entities.multipolygon.every(function(r) { return r.isComplete(graph); }))
68207             return 'incomplete_relation';
68208     };
68209
68210
68211     return action;
68212 }
68213
68214 // Copyright (c) 2006, 2008 Tony Garnock-Jones <tonyg@lshift.net>
68215 // Copyright (c) 2006, 2008 LShift Ltd. <query@lshift.net>
68216 //
68217 // Permission is hereby granted, free of charge, to any person
68218 // obtaining a copy of this software and associated documentation files
68219 // (the "Software"), to deal in the Software without restriction,
68220 // including without limitation the rights to use, copy, modify, merge,
68221 // publish, distribute, sublicense, and/or sell copies of the Software,
68222 // and to permit persons to whom the Software is furnished to do so,
68223 // subject to the following conditions:
68224 //
68225 // The above copyright notice and this permission notice shall be
68226 // included in all copies or substantial portions of the Software.
68227 //
68228 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
68229 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
68230 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
68231 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
68232 // BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
68233 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
68234 // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
68235 // SOFTWARE.
68236
68237 // source:  https://bitbucket.org/lshift/synchrotron/src
68238 function longest_common_subsequence(file1, file2) {
68239     /* Text diff algorithm following Hunt and McIlroy 1976.
68240      * J. W. Hunt and M. D. McIlroy, An algorithm for differential file
68241      * comparison, Bell Telephone Laboratories CSTR #41 (1976)
68242      * http://www.cs.dartmouth.edu/~doug/
68243      *
68244      * Expects two arrays of strings.
68245      */
68246     var equivalenceClasses;
68247     var file2indices;
68248     var newCandidate;
68249     var candidates;
68250     var line;
68251     var c, i, j, jX, r, s;
68252
68253     equivalenceClasses = {};
68254     for (j = 0; j < file2.length; j++) {
68255         line = file2[j];
68256         if (equivalenceClasses[line]) {
68257             equivalenceClasses[line].push(j);
68258         } else {
68259             equivalenceClasses[line] = [j];
68260         }
68261     }
68262
68263     candidates = [{file1index: -1,
68264                    file2index: -1,
68265                    chain: null}];
68266
68267     for (i = 0; i < file1.length; i++) {
68268         line = file1[i];
68269         file2indices = equivalenceClasses[line] || [];
68270
68271         r = 0;
68272         c = candidates[0];
68273
68274         for (jX = 0; jX < file2indices.length; jX++) {
68275             j = file2indices[jX];
68276
68277             for (s = 0; s < candidates.length; s++) {
68278                 if ((candidates[s].file2index < j) &&
68279                     ((s === candidates.length - 1) ||
68280                      (candidates[s + 1].file2index > j)))
68281                     break;
68282             }
68283
68284             if (s < candidates.length) {
68285                 newCandidate = {file1index: i,
68286                                 file2index: j,
68287                                 chain: candidates[s]};
68288                 if (r === candidates.length) {
68289                     candidates.push(c);
68290                 } else {
68291                     candidates[r] = c;
68292                 }
68293                 r = s + 1;
68294                 c = newCandidate;
68295                 if (r === candidates.length) {
68296                     break; // no point in examining further (j)s
68297                 }
68298             }
68299         }
68300
68301         candidates[r] = c;
68302     }
68303
68304     // At this point, we know the LCS: it's in the reverse of the
68305     // linked-list through .chain of
68306     // candidates[candidates.length - 1].
68307
68308     return candidates[candidates.length - 1];
68309 }
68310
68311
68312
68313
68314
68315
68316
68317
68318
68319
68320
68321 function diff_indices(file1, file2) {
68322     // We apply the LCS to give a simple representation of the
68323     // offsets and lengths of mismatched chunks in the input
68324     // files. This is used by diff3_merge_indices below.
68325
68326     var result = [];
68327     var tail1 = file1.length;
68328     var tail2 = file2.length;
68329
68330     for (var candidate = longest_common_subsequence(file1, file2);
68331          candidate !== null;
68332          candidate = candidate.chain)
68333     {
68334         var mismatchLength1 = tail1 - candidate.file1index - 1;
68335         var mismatchLength2 = tail2 - candidate.file2index - 1;
68336         tail1 = candidate.file1index;
68337         tail2 = candidate.file2index;
68338
68339         if (mismatchLength1 || mismatchLength2) {
68340             result.push({file1: [tail1 + 1, mismatchLength1],
68341                          file2: [tail2 + 1, mismatchLength2]});
68342         }
68343     }
68344
68345     result.reverse();
68346     return result;
68347 }
68348
68349 function diff3_merge_indices (a, o, b) {
68350     // Given three files, A, O, and B, where both A and B are
68351     // independently derived from O, returns a fairly complicated
68352     // internal representation of merge decisions it's taken. The
68353     // interested reader may wish to consult
68354     //
68355     // Sanjeev Khanna, Keshav Kunal, and Benjamin C. Pierce. "A
68356     // Formal Investigation of Diff3." In Arvind and Prasad,
68357     // editors, Foundations of Software Technology and Theoretical
68358     // Computer Science (FSTTCS), December 2007.
68359     //
68360     // (http://www.cis.upenn.edu/~bcpierce/papers/diff3-short.pdf)
68361     var i;
68362
68363     var m1 = diff_indices(o, a);
68364     var m2 = diff_indices(o, b);
68365
68366     var hunks = [];
68367     function addHunk(h, side) {
68368         hunks.push([h.file1[0], side, h.file1[1], h.file2[0], h.file2[1]]);
68369     }
68370     for (i = 0; i < m1.length; i++) { addHunk(m1[i], 0); }
68371     for (i = 0; i < m2.length; i++) { addHunk(m2[i], 2); }
68372     hunks.sort();
68373
68374     var result = [];
68375     var commonOffset = 0;
68376     function copyCommon(targetOffset) {
68377         if (targetOffset > commonOffset) {
68378             result.push([1, commonOffset, targetOffset - commonOffset]);
68379             commonOffset = targetOffset;
68380         }
68381     }
68382
68383     for (var hunkIndex = 0; hunkIndex < hunks.length; hunkIndex++) {
68384         var firstHunkIndex = hunkIndex;
68385         var hunk = hunks[hunkIndex];
68386         var regionLhs = hunk[0];
68387         var regionRhs = regionLhs + hunk[2];
68388         while (hunkIndex < hunks.length - 1) {
68389             var maybeOverlapping = hunks[hunkIndex + 1];
68390             var maybeLhs = maybeOverlapping[0];
68391             if (maybeLhs > regionRhs) break;
68392             regionRhs = maybeLhs + maybeOverlapping[2];
68393             hunkIndex++;
68394         }
68395
68396         copyCommon(regionLhs);
68397         if (firstHunkIndex === hunkIndex) {
68398     // The "overlap" was only one hunk long, meaning that
68399     // there's no conflict here. Either a and o were the
68400     // same, or b and o were the same.
68401             if (hunk[4] > 0) {
68402                 result.push([hunk[1], hunk[3], hunk[4]]);
68403             }
68404         } else {
68405     // A proper conflict. Determine the extents of the
68406     // regions involved from a, o and b. Effectively merge
68407     // all the hunks on the left into one giant hunk, and
68408     // do the same for the right; then, correct for skew
68409     // in the regions of o that each side changed, and
68410     // report appropriate spans for the three sides.
68411     var regions = {
68412         0: [a.length, -1, o.length, -1],
68413         2: [b.length, -1, o.length, -1]
68414     };
68415             for (i = firstHunkIndex; i <= hunkIndex; i++) {
68416         hunk = hunks[i];
68417                 var side = hunk[1];
68418         var r = regions[side];
68419         var oLhs = hunk[0];
68420         var oRhs = oLhs + hunk[2];
68421                 var abLhs = hunk[3];
68422                 var abRhs = abLhs + hunk[4];
68423         r[0] = Math.min(abLhs, r[0]);
68424         r[1] = Math.max(abRhs, r[1]);
68425         r[2] = Math.min(oLhs, r[2]);
68426         r[3] = Math.max(oRhs, r[3]);
68427             }
68428     var aLhs = regions[0][0] + (regionLhs - regions[0][2]);
68429     var aRhs = regions[0][1] + (regionRhs - regions[0][3]);
68430     var bLhs = regions[2][0] + (regionLhs - regions[2][2]);
68431     var bRhs = regions[2][1] + (regionRhs - regions[2][3]);
68432             result.push([-1,
68433              aLhs,      aRhs      - aLhs,
68434              regionLhs, regionRhs - regionLhs,
68435              bLhs,      bRhs      - bLhs]);
68436         }
68437         commonOffset = regionRhs;
68438     }
68439
68440     copyCommon(o.length);
68441     return result;
68442 }
68443
68444 function diff3_merge (a, o, b, excludeFalseConflicts) {
68445     // Applies the output of Diff3.diff3_merge_indices to actually
68446     // construct the merged file; the returned result alternates
68447     // between "ok" and "conflict" blocks.
68448
68449     var result = [];
68450     var files = [a, o, b];
68451     var indices = diff3_merge_indices(a, o, b);
68452
68453     var okLines = [];
68454     function flushOk() {
68455         if (okLines.length) {
68456             result.push({ok: okLines});
68457         }
68458         okLines = [];
68459     }
68460     function pushOk(xs) {
68461         for (var j = 0; j < xs.length; j++) {
68462             okLines.push(xs[j]);
68463         }
68464     }
68465
68466     function isTrueConflict(rec) {
68467         if (rec[2] !== rec[6]) return true;
68468         var aoff = rec[1];
68469         var boff = rec[5];
68470         for (var j = 0; j < rec[2]; j++) {
68471             if (a[j + aoff] !== b[j + boff]) return true;
68472         }
68473         return false;
68474     }
68475
68476     for (var i = 0; i < indices.length; i++) {
68477         var x = indices[i];
68478         var side = x[0];
68479         if (side === -1) {
68480             if (excludeFalseConflicts && !isTrueConflict(x)) {
68481                 pushOk(files[0].slice(x[1], x[1] + x[2]));
68482             } else {
68483                 flushOk();
68484                 result.push({conflict: {a: a.slice(x[1], x[1] + x[2]),
68485                                         aIndex: x[1],
68486                                         o: o.slice(x[3], x[3] + x[4]),
68487                                         oIndex: x[3],
68488                                         b: b.slice(x[5], x[5] + x[6]),
68489                                         bIndex: x[5]}});
68490             }
68491         } else {
68492             pushOk(files[side].slice(x[1], x[1] + x[2]));
68493         }
68494     }
68495
68496     flushOk();
68497     return result;
68498 }
68499
68500 function actionMergeRemoteChanges(id, localGraph, remoteGraph, formatUser) {
68501     var option = 'safe',  // 'safe', 'force_local', 'force_remote'
68502         conflicts = [];
68503
68504
68505     function user(d) {
68506         return lodash.isFunction(formatUser) ? formatUser(d) : d;
68507     }
68508
68509
68510     function mergeLocation(remote, target) {
68511         function pointEqual(a, b) {
68512             var epsilon = 1e-6;
68513             return (Math.abs(a[0] - b[0]) < epsilon) && (Math.abs(a[1] - b[1]) < epsilon);
68514         }
68515
68516         if (option === 'force_local' || pointEqual(target.loc, remote.loc)) {
68517             return target;
68518         }
68519         if (option === 'force_remote') {
68520             return target.update({loc: remote.loc});
68521         }
68522
68523         conflicts.push(t('merge_remote_changes.conflict.location', { user: user(remote.user) }));
68524         return target;
68525     }
68526
68527
68528     function mergeNodes(base, remote, target) {
68529         if (option === 'force_local' || lodash.isEqual(target.nodes, remote.nodes)) {
68530             return target;
68531         }
68532         if (option === 'force_remote') {
68533             return target.update({nodes: remote.nodes});
68534         }
68535
68536         var ccount = conflicts.length,
68537             o = base.nodes || [],
68538             a = target.nodes || [],
68539             b = remote.nodes || [],
68540             nodes = [],
68541             hunks = diff3_merge(a, o, b, true);
68542
68543         for (var i = 0; i < hunks.length; i++) {
68544             var hunk = hunks[i];
68545             if (hunk.ok) {
68546                 nodes.push.apply(nodes, hunk.ok);
68547             } else {
68548                 // for all conflicts, we can assume c.a !== c.b
68549                 // because `diff3_merge` called with `true` option to exclude false conflicts..
68550                 var c = hunk.conflict;
68551                 if (lodash.isEqual(c.o, c.a)) {  // only changed remotely
68552                     nodes.push.apply(nodes, c.b);
68553                 } else if (lodash.isEqual(c.o, c.b)) {  // only changed locally
68554                     nodes.push.apply(nodes, c.a);
68555                 } else {       // changed both locally and remotely
68556                     conflicts.push(t('merge_remote_changes.conflict.nodelist', { user: user(remote.user) }));
68557                     break;
68558                 }
68559             }
68560         }
68561
68562         return (conflicts.length === ccount) ? target.update({nodes: nodes}) : target;
68563     }
68564
68565
68566     function mergeChildren(targetWay, children, updates, graph) {
68567         function isUsed(node, targetWay) {
68568             var parentWays = lodash.map(graph.parentWays(node), 'id');
68569             return node.hasInterestingTags() ||
68570                 lodash.without(parentWays, targetWay.id).length > 0 ||
68571                 graph.parentRelations(node).length > 0;
68572         }
68573
68574         var ccount = conflicts.length;
68575
68576         for (var i = 0; i < children.length; i++) {
68577             var id = children[i],
68578                 node = graph.hasEntity(id);
68579
68580             // remove unused childNodes..
68581             if (targetWay.nodes.indexOf(id) === -1) {
68582                 if (node && !isUsed(node, targetWay)) {
68583                     updates.removeIds.push(id);
68584                 }
68585                 continue;
68586             }
68587
68588             // restore used childNodes..
68589             var local = localGraph.hasEntity(id),
68590                 remote = remoteGraph.hasEntity(id),
68591                 target;
68592
68593             if (option === 'force_remote' && remote && remote.visible) {
68594                 updates.replacements.push(remote);
68595
68596             } else if (option === 'force_local' && local) {
68597                 target = osmEntity$$1(local);
68598                 if (remote) {
68599                     target = target.update({ version: remote.version });
68600                 }
68601                 updates.replacements.push(target);
68602
68603             } else if (option === 'safe' && local && remote && local.version !== remote.version) {
68604                 target = osmEntity$$1(local, { version: remote.version });
68605                 if (remote.visible) {
68606                     target = mergeLocation(remote, target);
68607                 } else {
68608                     conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) }));
68609                 }
68610
68611                 if (conflicts.length !== ccount) break;
68612                 updates.replacements.push(target);
68613             }
68614         }
68615
68616         return targetWay;
68617     }
68618
68619
68620     function updateChildren(updates, graph) {
68621         for (var i = 0; i < updates.replacements.length; i++) {
68622             graph = graph.replace(updates.replacements[i]);
68623         }
68624         if (updates.removeIds.length) {
68625             graph = actionDeleteMultiple(updates.removeIds)(graph);
68626         }
68627         return graph;
68628     }
68629
68630
68631     function mergeMembers(remote, target) {
68632         if (option === 'force_local' || lodash.isEqual(target.members, remote.members)) {
68633             return target;
68634         }
68635         if (option === 'force_remote') {
68636             return target.update({members: remote.members});
68637         }
68638
68639         conflicts.push(t('merge_remote_changes.conflict.memberlist', { user: user(remote.user) }));
68640         return target;
68641     }
68642
68643
68644     function mergeTags(base, remote, target) {
68645         function ignoreKey(k) {
68646             return lodash.includes(dataDiscarded, k);
68647         }
68648
68649         if (option === 'force_local' || lodash.isEqual(target.tags, remote.tags)) {
68650             return target;
68651         }
68652         if (option === 'force_remote') {
68653             return target.update({tags: remote.tags});
68654         }
68655
68656         var ccount = conflicts.length,
68657             o = base.tags || {},
68658             a = target.tags || {},
68659             b = remote.tags || {},
68660             keys = lodash.reject(lodash.union(lodash.keys(o), lodash.keys(a), lodash.keys(b)), ignoreKey),
68661             tags = lodash.clone(a),
68662             changed = false;
68663
68664         for (var i = 0; i < keys.length; i++) {
68665             var k = keys[i];
68666
68667             if (o[k] !== b[k] && a[k] !== b[k]) {    // changed remotely..
68668                 if (o[k] !== a[k]) {      // changed locally..
68669                     conflicts.push(t('merge_remote_changes.conflict.tags',
68670                         { tag: k, local: a[k], remote: b[k], user: user(remote.user) }));
68671
68672                 } else {                  // unchanged locally, accept remote change..
68673                     if (b.hasOwnProperty(k)) {
68674                         tags[k] = b[k];
68675                     } else {
68676                         delete tags[k];
68677                     }
68678                     changed = true;
68679                 }
68680             }
68681         }
68682
68683         return (changed && conflicts.length === ccount) ? target.update({tags: tags}) : target;
68684     }
68685
68686
68687     //  `graph.base()` is the common ancestor of the two graphs.
68688     //  `localGraph` contains user's edits up to saving
68689     //  `remoteGraph` contains remote edits to modified nodes
68690     //  `graph` must be a descendent of `localGraph` and may include
68691     //      some conflict resolution actions performed on it.
68692     //
68693     //                  --- ... --- `localGraph` -- ... -- `graph`
68694     //                 /
68695     //  `graph.base()` --- ... --- `remoteGraph`
68696     //
68697     var action = function(graph) {
68698         var updates = { replacements: [], removeIds: [] },
68699             base = graph.base().entities[id],
68700             local = localGraph.entity(id),
68701             remote = remoteGraph.entity(id),
68702             target = osmEntity$$1(local, { version: remote.version });
68703
68704         // delete/undelete
68705         if (!remote.visible) {
68706             if (option === 'force_remote') {
68707                 return actionDeleteMultiple([id])(graph);
68708
68709             } else if (option === 'force_local') {
68710                 if (target.type === 'way') {
68711                     target = mergeChildren(target, lodash.uniq(local.nodes), updates, graph);
68712                     graph = updateChildren(updates, graph);
68713                 }
68714                 return graph.replace(target);
68715
68716             } else {
68717                 conflicts.push(t('merge_remote_changes.conflict.deleted', { user: user(remote.user) }));
68718                 return graph;  // do nothing
68719             }
68720         }
68721
68722         // merge
68723         if (target.type === 'node') {
68724             target = mergeLocation(remote, target);
68725
68726         } else if (target.type === 'way') {
68727             // pull in any child nodes that may not be present locally..
68728             graph.rebase(remoteGraph.childNodes(remote), [graph], false);
68729             target = mergeNodes(base, remote, target);
68730             target = mergeChildren(target, lodash.union(local.nodes, remote.nodes), updates, graph);
68731
68732         } else if (target.type === 'relation') {
68733             target = mergeMembers(remote, target);
68734         }
68735
68736         target = mergeTags(base, remote, target);
68737
68738         if (!conflicts.length) {
68739             graph = updateChildren(updates, graph).replace(target);
68740         }
68741
68742         return graph;
68743     };
68744
68745
68746     action.withOption = function(opt) {
68747         option = opt;
68748         return action;
68749     };
68750
68751
68752     action.conflicts = function() {
68753         return conflicts;
68754     };
68755
68756
68757     return action;
68758 }
68759
68760 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
68761 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
68762 function actionMove(moveIds, tryDelta, projection, cache) {
68763     var delta = tryDelta;
68764
68765     function vecAdd(a, b) { return [a[0] + b[0], a[1] + b[1]]; }
68766     function vecSub(a, b) { return [a[0] - b[0], a[1] - b[1]]; }
68767
68768     function setupCache(graph) {
68769         function canMove(nodeId) {
68770             // Allow movement of any node that is in the selectedIDs list..
68771             if (moveIds.indexOf(nodeId) !== -1) return true;
68772
68773             // Allow movement of a vertex where 2 ways meet..
68774             var parents = lodash.map(graph.parentWays(graph.entity(nodeId)), 'id');
68775             if (parents.length < 3) return true;
68776
68777             // Restrict movement of a vertex where >2 ways meet, unless all parentWays are moving too..
68778             var parentsMoving = lodash.every(parents, function(id) { return cache.moving[id]; });
68779             if (!parentsMoving) delete cache.moving[nodeId];
68780
68781             return parentsMoving;
68782         }
68783
68784         function cacheEntities(ids) {
68785             ids.forEach(function(id) {
68786                 if (cache.moving[id]) return;
68787                 cache.moving[id] = true;
68788
68789                 var entity = graph.hasEntity(id);
68790                 if (!entity) return;
68791
68792                 if (entity.type === 'node') {
68793                     cache.nodes.push(id);
68794                     cache.startLoc[id] = entity.loc;
68795                 } else if (entity.type === 'way') {
68796                     cache.ways.push(id);
68797                     cacheEntities(entity.nodes);
68798                 } else {
68799                     cacheEntities(entity.members.map(function(member) {
68800                         return member.id;
68801                     }));
68802                 }
68803             });
68804         }
68805
68806         function cacheIntersections(ids) {
68807             function isEndpoint(way, id) { return !way.isClosed() && !!way.affix(id); }
68808
68809             ids.forEach(function(id) {
68810                 // consider only intersections with 1 moved and 1 unmoved way.
68811                 var childNodes = graph.childNodes(graph.entity(id));
68812                 childNodes.forEach(function(node) {
68813                     var parents = graph.parentWays(node);
68814                     if (parents.length !== 2) return;
68815
68816                     var moved = graph.entity(id),
68817                         unmoved = lodash.find(parents, function(way) { return !cache.moving[way.id]; });
68818                     if (!unmoved) return;
68819
68820                     // exclude ways that are overly connected..
68821                     if (lodash.intersection(moved.nodes, unmoved.nodes).length > 2) return;
68822
68823                     if (moved.isArea() || unmoved.isArea()) return;
68824
68825                     cache.intersection[node.id] = {
68826                         nodeId: node.id,
68827                         movedId: moved.id,
68828                         unmovedId: unmoved.id,
68829                         movedIsEP: isEndpoint(moved, node.id),
68830                         unmovedIsEP: isEndpoint(unmoved, node.id)
68831                     };
68832                 });
68833             });
68834         }
68835
68836
68837         if (!cache) {
68838             cache = {};
68839         }
68840         if (!cache.ok) {
68841             cache.moving = {};
68842             cache.intersection = {};
68843             cache.replacedVertex = {};
68844             cache.startLoc = {};
68845             cache.nodes = [];
68846             cache.ways = [];
68847
68848             cacheEntities(moveIds);
68849             cacheIntersections(cache.ways);
68850             cache.nodes = lodash.filter(cache.nodes, canMove);
68851
68852             cache.ok = true;
68853         }
68854     }
68855
68856
68857     // Place a vertex where the moved vertex used to be, to preserve way shape..
68858     function replaceMovedVertex(nodeId, wayId, graph, delta) {
68859         var way = graph.entity(wayId),
68860             moved = graph.entity(nodeId),
68861             movedIndex = way.nodes.indexOf(nodeId),
68862             len, prevIndex, nextIndex;
68863
68864         if (way.isClosed()) {
68865             len = way.nodes.length - 1;
68866             prevIndex = (movedIndex + len - 1) % len;
68867             nextIndex = (movedIndex + len + 1) % len;
68868         } else {
68869             len = way.nodes.length;
68870             prevIndex = movedIndex - 1;
68871             nextIndex = movedIndex + 1;
68872         }
68873
68874         var prev = graph.hasEntity(way.nodes[prevIndex]),
68875             next = graph.hasEntity(way.nodes[nextIndex]);
68876
68877         // Don't add orig vertex at endpoint..
68878         if (!prev || !next) return graph;
68879
68880         var key = wayId + '_' + nodeId,
68881             orig = cache.replacedVertex[key];
68882         if (!orig) {
68883             orig = osmNode();
68884             cache.replacedVertex[key] = orig;
68885             cache.startLoc[orig.id] = cache.startLoc[nodeId];
68886         }
68887
68888         var start, end;
68889         if (delta) {
68890             start = projection(cache.startLoc[nodeId]);
68891             end = projection.invert(vecAdd(start, delta));
68892         } else {
68893             end = cache.startLoc[nodeId];
68894         }
68895         orig = orig.move(end);
68896
68897         var angle = Math.abs(geoAngle(orig, prev, projection) -
68898                 geoAngle(orig, next, projection)) * 180 / Math.PI;
68899
68900         // Don't add orig vertex if it would just make a straight line..
68901         if (angle > 175 && angle < 185) return graph;
68902
68903         // Don't add orig vertex if another point is already nearby (within 10m)
68904         if (geoSphericalDistance(prev.loc, orig.loc) < 10 ||
68905             geoSphericalDistance(orig.loc, next.loc) < 10) return graph;
68906
68907         // moving forward or backward along way?
68908         var p1 = [prev.loc, orig.loc, moved.loc, next.loc].map(projection),
68909             p2 = [prev.loc, moved.loc, orig.loc, next.loc].map(projection),
68910             d1 = geoPathLength(p1),
68911             d2 = geoPathLength(p2),
68912             insertAt = (d1 < d2) ? movedIndex : nextIndex;
68913
68914         // moving around closed loop?
68915         if (way.isClosed() && insertAt === 0) insertAt = len;
68916
68917         way = way.addNode(orig.id, insertAt);
68918         return graph.replace(orig).replace(way);
68919     }
68920
68921
68922     // Reorder nodes around intersections that have moved..
68923     function unZorroIntersection(intersection, graph) {
68924         var vertex = graph.entity(intersection.nodeId),
68925             way1 = graph.entity(intersection.movedId),
68926             way2 = graph.entity(intersection.unmovedId),
68927             isEP1 = intersection.movedIsEP,
68928             isEP2 = intersection.unmovedIsEP;
68929
68930         // don't move the vertex if it is the endpoint of both ways.
68931         if (isEP1 && isEP2) return graph;
68932
68933         var nodes1 = lodash.without(graph.childNodes(way1), vertex),
68934             nodes2 = lodash.without(graph.childNodes(way2), vertex);
68935
68936         if (way1.isClosed() && way1.first() === vertex.id) nodes1.push(nodes1[0]);
68937         if (way2.isClosed() && way2.first() === vertex.id) nodes2.push(nodes2[0]);
68938
68939         var edge1 = !isEP1 && geoChooseEdge(nodes1, projection(vertex.loc), projection),
68940             edge2 = !isEP2 && geoChooseEdge(nodes2, projection(vertex.loc), projection),
68941             loc;
68942
68943         // snap vertex to nearest edge (or some point between them)..
68944         if (!isEP1 && !isEP2) {
68945             var epsilon = 1e-4, maxIter = 10;
68946             for (var i = 0; i < maxIter; i++) {
68947                 loc = geoInterp(edge1.loc, edge2.loc, 0.5);
68948                 edge1 = geoChooseEdge(nodes1, projection(loc), projection);
68949                 edge2 = geoChooseEdge(nodes2, projection(loc), projection);
68950                 if (Math.abs(edge1.distance - edge2.distance) < epsilon) break;
68951             }
68952         } else if (!isEP1) {
68953             loc = edge1.loc;
68954         } else {
68955             loc = edge2.loc;
68956         }
68957
68958         graph = graph.replace(vertex.move(loc));
68959
68960         // if zorro happened, reorder nodes..
68961         if (!isEP1 && edge1.index !== way1.nodes.indexOf(vertex.id)) {
68962             way1 = way1.removeNode(vertex.id).addNode(vertex.id, edge1.index);
68963             graph = graph.replace(way1);
68964         }
68965         if (!isEP2 && edge2.index !== way2.nodes.indexOf(vertex.id)) {
68966             way2 = way2.removeNode(vertex.id).addNode(vertex.id, edge2.index);
68967             graph = graph.replace(way2);
68968         }
68969
68970         return graph;
68971     }
68972
68973
68974     function cleanupIntersections(graph) {
68975         lodash.each(cache.intersection, function(obj) {
68976             graph = replaceMovedVertex(obj.nodeId, obj.movedId, graph, delta);
68977             graph = replaceMovedVertex(obj.nodeId, obj.unmovedId, graph, null);
68978             graph = unZorroIntersection(obj, graph);
68979         });
68980
68981         return graph;
68982     }
68983
68984
68985     // check if moving way endpoint can cross an unmoved way, if so limit delta..
68986     function limitDelta(graph) {
68987         lodash.each(cache.intersection, function(obj) {
68988             // Don't limit movement if this is vertex joins 2 endpoints..
68989             if (obj.movedIsEP && obj.unmovedIsEP) return;
68990             // Don't limit movement if this vertex is not an endpoint anyway..
68991             if (!obj.movedIsEP) return;
68992
68993             var node = graph.entity(obj.nodeId),
68994                 start = projection(node.loc),
68995                 end = vecAdd(start, delta),
68996                 movedNodes = graph.childNodes(graph.entity(obj.movedId)),
68997                 movedPath = lodash.map(lodash.map(movedNodes, 'loc'),
68998                     function(loc) { return vecAdd(projection(loc), delta); }),
68999                 unmovedNodes = graph.childNodes(graph.entity(obj.unmovedId)),
69000                 unmovedPath = lodash.map(lodash.map(unmovedNodes, 'loc'), projection),
69001                 hits = geoPathIntersections(movedPath, unmovedPath);
69002
69003             for (var i = 0; i < hits.length; i++) {
69004                 if (lodash.isEqual(hits[i], end)) continue;
69005                 var edge = geoChooseEdge(unmovedNodes, end, projection);
69006                 delta = vecSub(projection(edge.loc), start);
69007             }
69008         });
69009     }
69010
69011
69012     var action = function(graph) {
69013         if (delta[0] === 0 && delta[1] === 0) return graph;
69014
69015         setupCache(graph);
69016
69017         if (!lodash.isEmpty(cache.intersection)) {
69018             limitDelta(graph);
69019         }
69020
69021         lodash.each(cache.nodes, function(id) {
69022             var node = graph.entity(id),
69023                 start = projection(node.loc),
69024                 end = vecAdd(start, delta);
69025             graph = graph.replace(node.move(projection.invert(end)));
69026         });
69027
69028         if (!lodash.isEmpty(cache.intersection)) {
69029             graph = cleanupIntersections(graph);
69030         }
69031
69032         return graph;
69033     };
69034
69035
69036     action.disabled = function(graph) {
69037         function incompleteRelation(id) {
69038             var entity = graph.entity(id);
69039             return entity.type === 'relation' && !entity.isComplete(graph);
69040         }
69041
69042         if (lodash.some(moveIds, incompleteRelation))
69043             return 'incomplete_relation';
69044     };
69045
69046
69047     action.delta = function() {
69048         return delta;
69049     };
69050
69051
69052     return action;
69053 }
69054
69055 // https://github.com/openstreetmap/josm/blob/mirror/src/org/openstreetmap/josm/command/MoveCommand.java
69056 // https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/MoveNodeAction.as
69057 function actionMoveNode(nodeId, loc) {
69058     return function(graph) {
69059         return graph.replace(graph.entity(nodeId).move(loc));
69060     };
69061 }
69062
69063 function actionNoop() {
69064     return function(graph) {
69065         return graph;
69066     };
69067 }
69068
69069 /*
69070  * Based on https://github.com/openstreetmap/potlatch2/blob/master/net/systemeD/potlatch2/tools/Quadrilateralise.as
69071  */
69072 function actionOrthogonalize(wayId, projection) {
69073     var threshold = 12, // degrees within right or straight to alter
69074         lowerThreshold = Math.cos((90 - threshold) * Math.PI / 180),
69075         upperThreshold = Math.cos(threshold * Math.PI / 180);
69076
69077
69078     var action = function(graph) {
69079         var way = graph.entity(wayId),
69080             nodes = graph.childNodes(way),
69081             points = lodash.uniq(nodes).map(function(n) { return projection(n.loc); }),
69082             corner = {i: 0, dotp: 1},
69083             epsilon = 1e-4,
69084             i, j, score, motions;
69085
69086         if (nodes.length === 4) {
69087             for (i = 0; i < 1000; i++) {
69088                 motions = points.map(calcMotion);
69089                 points[corner.i] = addPoints(points[corner.i],motions[corner.i]);
69090                 score = corner.dotp;
69091                 if (score < epsilon) {
69092                     break;
69093                 }
69094             }
69095
69096             graph = graph.replace(graph.entity(nodes[corner.i].id)
69097                 .move(projection.invert(points[corner.i])));
69098
69099         } else {
69100             var best,
69101                 originalPoints = lodash.clone(points);
69102             score = Infinity;
69103
69104             for (i = 0; i < 1000; i++) {
69105                 motions = points.map(calcMotion);
69106                 for (j = 0; j < motions.length; j++) {
69107                     points[j] = addPoints(points[j],motions[j]);
69108                 }
69109                 var newScore = squareness(points);
69110                 if (newScore < score) {
69111                     best = lodash.clone(points);
69112                     score = newScore;
69113                 }
69114                 if (score < epsilon) {
69115                     break;
69116                 }
69117             }
69118
69119             points = best;
69120
69121             for (i = 0; i < points.length; i++) {
69122                 // only move the points that actually moved
69123                 if (originalPoints[i][0] !== points[i][0] || originalPoints[i][1] !== points[i][1]) {
69124                     graph = graph.replace(graph.entity(nodes[i].id)
69125                         .move(projection.invert(points[i])));
69126                 }
69127             }
69128
69129             // remove empty nodes on straight sections
69130             for (i = 0; i < points.length; i++) {
69131                 var node = nodes[i];
69132
69133                 if (graph.parentWays(node).length > 1 ||
69134                     graph.parentRelations(node).length ||
69135                     node.hasInterestingTags()) {
69136
69137                     continue;
69138                 }
69139
69140                 var dotp = normalizedDotProduct(i, points);
69141                 if (dotp < -1 + epsilon) {
69142                     graph = actionDeleteNode(nodes[i].id)(graph);
69143                 }
69144             }
69145         }
69146
69147         return graph;
69148
69149
69150         function calcMotion(b, i, array) {
69151             var a = array[(i - 1 + array.length) % array.length],
69152                 c = array[(i + 1) % array.length],
69153                 p = subtractPoints(a, b),
69154                 q = subtractPoints(c, b),
69155                 scale, dotp;
69156
69157             scale = 2 * Math.min(geoEuclideanDistance(p, [0, 0]), geoEuclideanDistance(q, [0, 0]));
69158             p = normalizePoint(p, 1.0);
69159             q = normalizePoint(q, 1.0);
69160
69161             dotp = filterDotProduct(p[0] * q[0] + p[1] * q[1]);
69162
69163             // nasty hack to deal with almost-straight segments (angle is closer to 180 than to 90/270).
69164             if (array.length > 3) {
69165                 if (dotp < -0.707106781186547) {
69166                     dotp += 1.0;
69167                 }
69168             } else if (dotp && Math.abs(dotp) < corner.dotp) {
69169                 corner.i = i;
69170                 corner.dotp = Math.abs(dotp);
69171             }
69172
69173             return normalizePoint(addPoints(p, q), 0.1 * dotp * scale);
69174         }
69175     };
69176
69177
69178     function squareness(points) {
69179         return points.reduce(function(sum, val, i, array) {
69180             var dotp = normalizedDotProduct(i, array);
69181
69182             dotp = filterDotProduct(dotp);
69183             return sum + 2.0 * Math.min(Math.abs(dotp - 1.0), Math.min(Math.abs(dotp), Math.abs(dotp + 1)));
69184         }, 0);
69185     }
69186
69187
69188     function normalizedDotProduct(i, points) {
69189         var a = points[(i - 1 + points.length) % points.length],
69190             b = points[i],
69191             c = points[(i + 1) % points.length],
69192             p = subtractPoints(a, b),
69193             q = subtractPoints(c, b);
69194
69195         p = normalizePoint(p, 1.0);
69196         q = normalizePoint(q, 1.0);
69197
69198         return p[0] * q[0] + p[1] * q[1];
69199     }
69200
69201
69202     function subtractPoints(a, b) {
69203         return [a[0] - b[0], a[1] - b[1]];
69204     }
69205
69206
69207     function addPoints(a, b) {
69208         return [a[0] + b[0], a[1] + b[1]];
69209     }
69210
69211
69212     function normalizePoint(point, scale) {
69213         var vector = [0, 0];
69214         var length = Math.sqrt(point[0] * point[0] + point[1] * point[1]);
69215         if (length !== 0) {
69216             vector[0] = point[0] / length;
69217             vector[1] = point[1] / length;
69218         }
69219
69220         vector[0] *= scale;
69221         vector[1] *= scale;
69222
69223         return vector;
69224     }
69225
69226
69227     function filterDotProduct(dotp) {
69228         if (lowerThreshold > Math.abs(dotp) || Math.abs(dotp) > upperThreshold) {
69229             return dotp;
69230         }
69231
69232         return 0;
69233     }
69234
69235
69236     action.disabled = function(graph) {
69237         var way = graph.entity(wayId),
69238             nodes = graph.childNodes(way),
69239             points = lodash.uniq(nodes).map(function(n) { return projection(n.loc); });
69240
69241         if (squareness(points)) {
69242             return false;
69243         }
69244
69245         return 'not_squarish';
69246     };
69247
69248
69249     return action;
69250 }
69251
69252 // Split a way at the given node.
69253 //
69254 // Optionally, split only the given ways, if multiple ways share
69255 // the given node.
69256 //
69257 // This is the inverse of `iD.actionJoin`.
69258 //
69259 // For testing convenience, accepts an ID to assign to the new way.
69260 // Normally, this will be undefined and the way will automatically
69261 // be assigned a new ID.
69262 //
69263 // Reference:
69264 //   https://github.com/systemed/potlatch2/blob/master/net/systemeD/halcyon/connection/actions/SplitWayAction.as
69265 //
69266 function actionSplit(nodeId, newWayIds) {
69267     var wayIds;
69268
69269     // if the way is closed, we need to search for a partner node
69270     // to split the way at.
69271     //
69272     // The following looks for a node that is both far away from
69273     // the initial node in terms of way segment length and nearby
69274     // in terms of beeline-distance. This assures that areas get
69275     // split on the most "natural" points (independent of the number
69276     // of nodes).
69277     // For example: bone-shaped areas get split across their waist
69278     // line, circles across the diameter.
69279     function splitArea(nodes, idxA, graph) {
69280         var lengths = new Array(nodes.length),
69281             length,
69282             i,
69283             best = 0,
69284             idxB;
69285
69286         function wrap(index) {
69287             return utilWrap(index, nodes.length);
69288         }
69289
69290         function dist(nA, nB) {
69291             return geoSphericalDistance(graph.entity(nA).loc, graph.entity(nB).loc);
69292         }
69293
69294         // calculate lengths
69295         length = 0;
69296         for (i = wrap(idxA+1); i !== idxA; i = wrap(i+1)) {
69297             length += dist(nodes[i], nodes[wrap(i-1)]);
69298             lengths[i] = length;
69299         }
69300
69301         length = 0;
69302         for (i = wrap(idxA-1); i !== idxA; i = wrap(i-1)) {
69303             length += dist(nodes[i], nodes[wrap(i+1)]);
69304             if (length < lengths[i])
69305                 lengths[i] = length;
69306         }
69307
69308         // determine best opposite node to split
69309         for (i = 0; i < nodes.length; i++) {
69310             var cost = lengths[i] / dist(nodes[idxA], nodes[i]);
69311             if (cost > best) {
69312                 idxB = i;
69313                 best = cost;
69314             }
69315         }
69316
69317         return idxB;
69318     }
69319
69320
69321     function split(graph, wayA, newWayId) {
69322         var wayB = osmWay({id: newWayId, tags: wayA.tags}),
69323             nodesA,
69324             nodesB,
69325             isArea = wayA.isArea(),
69326             isOuter = osmIsSimpleMultipolygonOuterMember(wayA, graph);
69327
69328         if (wayA.isClosed()) {
69329             var nodes = wayA.nodes.slice(0, -1),
69330                 idxA = lodash.indexOf(nodes, nodeId),
69331                 idxB = splitArea(nodes, idxA, graph);
69332
69333             if (idxB < idxA) {
69334                 nodesA = nodes.slice(idxA).concat(nodes.slice(0, idxB + 1));
69335                 nodesB = nodes.slice(idxB, idxA + 1);
69336             } else {
69337                 nodesA = nodes.slice(idxA, idxB + 1);
69338                 nodesB = nodes.slice(idxB).concat(nodes.slice(0, idxA + 1));
69339             }
69340         } else {
69341             var idx = lodash.indexOf(wayA.nodes, nodeId, 1);
69342             nodesA = wayA.nodes.slice(0, idx + 1);
69343             nodesB = wayA.nodes.slice(idx);
69344         }
69345
69346         wayA = wayA.update({nodes: nodesA});
69347         wayB = wayB.update({nodes: nodesB});
69348
69349         graph = graph.replace(wayA);
69350         graph = graph.replace(wayB);
69351
69352         graph.parentRelations(wayA).forEach(function(relation) {
69353             if (relation.isRestriction()) {
69354                 var via = relation.memberByRole('via');
69355                 if (via && wayB.contains(via.id)) {
69356                     relation = relation.updateMember({id: wayB.id}, relation.memberById(wayA.id).index);
69357                     graph = graph.replace(relation);
69358                 }
69359             } else {
69360                 if (relation === isOuter) {
69361                     graph = graph.replace(relation.mergeTags(wayA.tags));
69362                     graph = graph.replace(wayA.update({tags: {}}));
69363                     graph = graph.replace(wayB.update({tags: {}}));
69364                 }
69365
69366                 var member = {
69367                     id: wayB.id,
69368                     type: 'way',
69369                     role: relation.memberById(wayA.id).role
69370                 };
69371
69372                 graph = actionAddMember(relation.id, member)(graph);
69373             }
69374         });
69375
69376         if (!isOuter && isArea) {
69377             var multipolygon = osmRelation({
69378                 tags: lodash.extend({}, wayA.tags, {type: 'multipolygon'}),
69379                 members: [
69380                     {id: wayA.id, role: 'outer', type: 'way'},
69381                     {id: wayB.id, role: 'outer', type: 'way'}
69382                 ]});
69383
69384             graph = graph.replace(multipolygon);
69385             graph = graph.replace(wayA.update({tags: {}}));
69386             graph = graph.replace(wayB.update({tags: {}}));
69387         }
69388
69389         return graph;
69390     }
69391
69392
69393     var action = function(graph) {
69394         var candidates = action.ways(graph);
69395         for (var i = 0; i < candidates.length; i++) {
69396             graph = split(graph, candidates[i], newWayIds && newWayIds[i]);
69397         }
69398         return graph;
69399     };
69400
69401
69402     action.ways = function(graph) {
69403         var node = graph.entity(nodeId),
69404             parents = graph.parentWays(node),
69405             hasLines = lodash.some(parents, function(parent) { return parent.geometry(graph) === 'line'; });
69406
69407         return parents.filter(function(parent) {
69408             if (wayIds && wayIds.indexOf(parent.id) === -1)
69409                 return false;
69410
69411             if (!wayIds && hasLines && parent.geometry(graph) !== 'line')
69412                 return false;
69413
69414             if (parent.isClosed()) {
69415                 return true;
69416             }
69417
69418             for (var i = 1; i < parent.nodes.length - 1; i++) {
69419                 if (parent.nodes[i] === nodeId) {
69420                     return true;
69421                 }
69422             }
69423
69424             return false;
69425         });
69426     };
69427
69428
69429     action.disabled = function(graph) {
69430         var candidates = action.ways(graph);
69431         if (candidates.length === 0 || (wayIds && wayIds.length !== candidates.length))
69432             return 'not_eligible';
69433     };
69434
69435
69436     action.limitWays = function(_) {
69437         if (!arguments.length) return wayIds;
69438         wayIds = _;
69439         return action;
69440     };
69441
69442
69443     return action;
69444 }
69445
69446 // Create a restriction relation for `turn`, which must have the following structure:
69447 //
69448 //     {
69449 //         from: { node: <node ID>, way: <way ID> },
69450 //         via:  { node: <node ID> },
69451 //         to:   { node: <node ID>, way: <way ID> },
69452 //         restriction: <'no_right_turn', 'no_left_turn', etc.>
69453 //     }
69454 //
69455 // This specifies a restriction of type `restriction` when traveling from
69456 // `from.node` in `from.way` toward `to.node` in `to.way` via `via.node`.
69457 // (The action does not check that these entities form a valid intersection.)
69458 //
69459 // If `restriction` is not provided, it is automatically determined by
69460 // osmInferRestriction.
69461 //
69462 // If necessary, the `from` and `to` ways are split. In these cases, `from.node`
69463 // and `to.node` are used to determine which portion of the split ways become
69464 // members of the restriction.
69465 //
69466 // For testing convenience, accepts an ID to assign to the new relation.
69467 // Normally, this will be undefined and the relation will automatically
69468 // be assigned a new ID.
69469 //
69470 function actionRestrictTurn(turn, projection, restrictionId) {
69471
69472     return function(graph) {
69473         var from = graph.entity(turn.from.way),
69474             via  = graph.entity(turn.via.node),
69475             to   = graph.entity(turn.to.way);
69476
69477         function isClosingNode(way, nodeId) {
69478             return nodeId === way.first() && nodeId === way.last();
69479         }
69480
69481         function split(toOrFrom) {
69482             var newID = toOrFrom.newID || osmWay().id;
69483             graph = actionSplit(via.id, [newID])
69484                 .limitWays([toOrFrom.way])(graph);
69485
69486             var a = graph.entity(newID),
69487                 b = graph.entity(toOrFrom.way);
69488
69489             if (a.nodes.indexOf(toOrFrom.node) !== -1) {
69490                 return [a, b];
69491             } else {
69492                 return [b, a];
69493             }
69494         }
69495
69496         if (!from.affix(via.id) || isClosingNode(from, via.id)) {
69497             if (turn.from.node === turn.to.node) {
69498                 // U-turn
69499                 from = to = split(turn.from)[0];
69500             } else if (turn.from.way === turn.to.way) {
69501                 // Straight-on or circular
69502                 var s = split(turn.from);
69503                 from = s[0];
69504                 to   = s[1];
69505             } else {
69506                 // Other
69507                 from = split(turn.from)[0];
69508             }
69509         }
69510
69511         if (!to.affix(via.id) || isClosingNode(to, via.id)) {
69512             to = split(turn.to)[0];
69513         }
69514
69515         return graph.replace(osmRelation({
69516             id: restrictionId,
69517             tags: {
69518                 type: 'restriction',
69519                 restriction: turn.restriction ||
69520                     osmInferRestriction(
69521                         graph,
69522                         turn.from,
69523                         turn.via,
69524                         turn.to,
69525                         projection)
69526             },
69527             members: [
69528                 {id: from.id, type: 'way',  role: 'from'},
69529                 {id: via.id,  type: 'node', role: 'via'},
69530                 {id: to.id,   type: 'way',  role: 'to'}
69531             ]
69532         }));
69533     };
69534 }
69535
69536 function actionRevert(id) {
69537     var action = function(graph) {
69538         var entity = graph.hasEntity(id),
69539             base = graph.base().entities[id];
69540
69541         if (entity && !base) {    // entity will be removed..
69542             if (entity.type === 'node') {
69543                 graph.parentWays(entity)
69544                     .forEach(function(parent) {
69545                         parent = parent.removeNode(id);
69546                         graph = graph.replace(parent);
69547
69548                         if (parent.isDegenerate()) {
69549                             graph = actionDeleteWay(parent.id)(graph);
69550                         }
69551                     });
69552             }
69553
69554             graph.parentRelations(entity)
69555                 .forEach(function(parent) {
69556                     parent = parent.removeMembersWithID(id);
69557                     graph = graph.replace(parent);
69558
69559                     if (parent.isDegenerate()) {
69560                         graph = actionDeleteRelation(parent.id)(graph);
69561                     }
69562                 });
69563         }
69564
69565         return graph.revert(id);
69566     };
69567
69568     return action;
69569 }
69570
69571 function actionRotateWay(wayId, pivot, angle, projection) {
69572     return function(graph) {
69573         return graph.update(function(graph) {
69574             var way = graph.entity(wayId);
69575
69576             lodash.uniq(way.nodes).forEach(function(id) {
69577
69578                 var node = graph.entity(id),
69579                     point = projection(node.loc),
69580                     radial = [0,0];
69581
69582                 radial[0] = point[0] - pivot[0];
69583                 radial[1] = point[1] - pivot[1];
69584
69585                 point = [
69586                     radial[0] * Math.cos(angle) - radial[1] * Math.sin(angle) + pivot[0],
69587                     radial[0] * Math.sin(angle) + radial[1] * Math.cos(angle) + pivot[1]
69588                 ];
69589
69590                 graph = graph.replace(node.move(projection.invert(point)));
69591
69592             });
69593
69594         });
69595     };
69596 }
69597
69598 /*
69599  * Based on https://github.com/openstreetmap/potlatch2/net/systemeD/potlatch2/tools/Straighten.as
69600  */
69601 function actionStraighten(wayId, projection) {
69602
69603     function positionAlongWay(n, s, e) {
69604         return ((n[0] - s[0]) * (e[0] - s[0]) + (n[1] - s[1]) * (e[1] - s[1]))/
69605                 (Math.pow(e[0] - s[0], 2) + Math.pow(e[1] - s[1], 2));
69606     }
69607
69608
69609     var action = function(graph) {
69610         var way = graph.entity(wayId),
69611             nodes = graph.childNodes(way),
69612             points = nodes.map(function(n) { return projection(n.loc); }),
69613             startPoint = points[0],
69614             endPoint = points[points.length-1],
69615             toDelete = [],
69616             i;
69617
69618         for (i = 1; i < points.length-1; i++) {
69619             var node = nodes[i],
69620                 point = points[i];
69621
69622             if (graph.parentWays(node).length > 1 ||
69623                 graph.parentRelations(node).length ||
69624                 node.hasInterestingTags()) {
69625
69626                 var u = positionAlongWay(point, startPoint, endPoint),
69627                     p0 = startPoint[0] + u * (endPoint[0] - startPoint[0]),
69628                     p1 = startPoint[1] + u * (endPoint[1] - startPoint[1]);
69629
69630                 graph = graph
69631                     .replace(graph.entity(node.id)
69632                     .move(projection.invert([p0, p1])));
69633
69634             } else {
69635                 // safe to delete
69636                 if (toDelete.indexOf(node) === -1) {
69637                     toDelete.push(node);
69638                 }
69639             }
69640         }
69641
69642         for (i = 0; i < toDelete.length; i++) {
69643             graph = actionDeleteNode(toDelete[i].id)(graph);
69644         }
69645
69646         return graph;
69647     };
69648
69649
69650     action.disabled = function(graph) {
69651         // check way isn't too bendy
69652         var way = graph.entity(wayId),
69653             nodes = graph.childNodes(way),
69654             points = nodes.map(function(n) { return projection(n.loc); }),
69655             startPoint = points[0],
69656             endPoint = points[points.length-1],
69657             threshold = 0.2 * geoEuclideanDistance(startPoint, endPoint),
69658             i;
69659
69660         if (threshold === 0) {
69661             return 'too_bendy';
69662         }
69663
69664         for (i = 1; i < points.length-1; i++) {
69665             var point = points[i],
69666                 u = positionAlongWay(point, startPoint, endPoint),
69667                 p0 = startPoint[0] + u * (endPoint[0] - startPoint[0]),
69668                 p1 = startPoint[1] + u * (endPoint[1] - startPoint[1]),
69669                 dist = Math.sqrt(Math.pow(p0 - point[0], 2) + Math.pow(p1 - point[1], 2));
69670
69671             // to bendy if point is off by 20% of total start/end distance in projected space
69672             if (isNaN(dist) || dist > threshold) {
69673                 return 'too_bendy';
69674             }
69675         }
69676     };
69677
69678
69679     return action;
69680 }
69681
69682 // Remove the effects of `turn.restriction` on `turn`, which must have the
69683 // following structure:
69684 //
69685 //     {
69686 //         from: { node: <node ID>, way: <way ID> },
69687 //         via:  { node: <node ID> },
69688 //         to:   { node: <node ID>, way: <way ID> },
69689 //         restriction: <relation ID>
69690 //     }
69691 //
69692 // In the simple case, `restriction` is a reference to a `no_*` restriction
69693 // on the turn itself. In this case, it is simply deleted.
69694 //
69695 // The more complex case is where `restriction` references an `only_*`
69696 // restriction on a different turn in the same intersection. In that case,
69697 // that restriction is also deleted, but at the same time restrictions on
69698 // the turns other than the first two are created.
69699 //
69700 function actionUnrestrictTurn(turn) {
69701     return function(graph) {
69702         return actionDeleteRelation(turn.restriction)(graph);
69703     };
69704 }
69705
69706
69707
69708 var index$16 = Object.freeze({
69709         d3combobox: d3combobox,
69710         d3geoTile: d3geoTile,
69711         d3keybinding: d3keybinding
69712 });
69713
69714 /* export some legacy symbols: */
69715 var Connection = services.osm;
69716 var debug = false;
69717
69718
69719
69720
69721 var iD = Object.freeze({
69722         Connection: Connection,
69723         debug: debug,
69724         d3: index$1,
69725         lib: index$16,
69726         Context: coreContext,
69727         setAreaKeys: setAreaKeys,
69728         Difference: coreDifference,
69729         Graph: coreGraph$$1,
69730         History: coreHistory,
69731         Tree: coreTree,
69732         Entity: osmEntity$$1,
69733         Node: osmNode,
69734         Relation: osmRelation,
69735         Way: osmWay,
69736         BackgroundSource: rendererBackgroundSource,
69737         Background: rendererBackground,
69738         Features: rendererFeatures,
69739         Map: rendererMap,
69740         TileLayer: rendererTileLayer,
69741         Detect: utilDetect,
69742         actionAddEntity: actionAddEntity,
69743         actionAddMember: actionAddMember,
69744         actionAddMidpoint: actionAddMidpoint,
69745         actionAddVertex: actionAddVertex,
69746         actionChangeMember: actionChangeMember,
69747         actionChangePreset: actionChangePreset,
69748         actionChangeTags: actionChangeTags,
69749         actionCircularize: actionCircularize,
69750         actionConnect: actionConnect,
69751         actionCopyEntities: actionCopyEntities,
69752         actionDeleteMember: actionDeleteMember,
69753         actionDeleteMultiple: actionDeleteMultiple,
69754         actionDeleteNode: actionDeleteNode,
69755         actionDeleteRelation: actionDeleteRelation,
69756         actionDeleteWay: actionDeleteWay,
69757         actionDeprecateTags: actionDeprecateTags,
69758         actionDiscardTags: actionDiscardTags,
69759         actionDisconnect: actionDisconnect,
69760         actionJoin: actionJoin,
69761         actionMerge: actionMerge,
69762         actionMergePolygon: actionMergePolygon,
69763         actionMergeRemoteChanges: actionMergeRemoteChanges,
69764         actionMove: actionMove,
69765         actionMoveNode: actionMoveNode,
69766         actionNoop: actionNoop,
69767         actionOrthogonalize: actionOrthogonalize,
69768         actionRestrictTurn: actionRestrictTurn,
69769         actionReverse: actionReverse,
69770         actionRevert: actionRevert,
69771         actionRotateWay: actionRotateWay,
69772         actionSplit: actionSplit,
69773         actionStraighten: actionStraighten,
69774         actionUnrestrictTurn: actionUnrestrictTurn,
69775         behaviorAddWay: behaviorAddWay,
69776         behaviorBreathe: behaviorBreathe,
69777         behaviorCopy: behaviorCopy,
69778         behaviorDrag: behaviorDrag,
69779         behaviorDrawWay: behaviorDrawWay,
69780         behaviorDraw: behaviorDraw,
69781         behaviorEdit: behaviorEdit,
69782         behaviorHash: behaviorHash,
69783         behaviorHover: behaviorHover,
69784         behaviorLasso: behaviorLasso,
69785         behaviorPaste: behaviorPaste,
69786         behaviorSelect: behaviorSelect,
69787         behaviorTail: behaviorTail,
69788         coreContext: coreContext,
69789         coreDifference: coreDifference,
69790         coreGraph: coreGraph$$1,
69791         coreHistory: coreHistory,
69792         coreTree: coreTree,
69793         data: data,
69794         dataWikipedia: dataWikipedia,
69795         dataFeatureIcons: dataFeatureIcons,
69796         dataSuggestions: dataSuggestions,
69797         dataAddressFormats: dataAddressFormats,
69798         dataDeprecated: dataDeprecated,
69799         dataDiscarded: dataDiscarded,
69800         dataLocales: dataLocales,
69801         dataPhoneFormats: dataPhoneFormats,
69802         dataImperial: dataImperial,
69803         dataDriveLeft: dataDriveLeft,
69804         dataEn: en,
69805         geoRoundCoords: geoRoundCoords,
69806         geoInterp: geoInterp,
69807         geoCross: geoCross,
69808         geoEuclideanDistance: geoEuclideanDistance,
69809         geoLatToMeters: geoLatToMeters,
69810         geoLonToMeters: geoLonToMeters,
69811         geoMetersToLat: geoMetersToLat,
69812         geoMetersToLon: geoMetersToLon,
69813         geoOffsetToMeters: geoOffsetToMeters,
69814         geoMetersToOffset: geoMetersToOffset,
69815         geoSphericalDistance: geoSphericalDistance,
69816         geoEdgeEqual: geoEdgeEqual,
69817         geoAngle: geoAngle,
69818         geoChooseEdge: geoChooseEdge,
69819         geoLineIntersection: geoLineIntersection,
69820         geoPathIntersections: geoPathIntersections,
69821         geoPointInPolygon: geoPointInPolygon,
69822         geoPolygonContainsPolygon: geoPolygonContainsPolygon,
69823         geoPolygonIntersectsPolygon: geoPolygonIntersectsPolygon,
69824         geoPathLength: geoPathLength,
69825         geoExtent: geoExtent$$1,
69826         geoRawMercator: geoRawMercator,
69827         modeAddArea: modeAddArea$$1,
69828         modeAddLine: modeAddLine$$1,
69829         modeAddPoint: modeAddPoint$$1,
69830         modeBrowse: modeBrowse$$1,
69831         modeDragNode: modeDragNode$$1,
69832         modeDrawArea: modeDrawArea,
69833         modeDrawLine: modeDrawLine,
69834         modeMove: modeMove$$1,
69835         modeRotateWay: modeRotateWay$$1,
69836         modeSave: modeSave$$1,
69837         modeSelect: modeSelect,
69838         operationCircularize: operationCircularize,
69839         operationContinue: operationContinue,
69840         operationDelete: operationDelete,
69841         operationDisconnect: operationDisconnect,
69842         operationMerge: operationMerge,
69843         operationMove: operationMove,
69844         operationOrthogonalize: operationOrthogonalize,
69845         operationReverse: operationReverse,
69846         operationRotate: operationRotate,
69847         operationSplit: operationSplit,
69848         operationStraighten: operationStraighten,
69849         osmEntity: osmEntity$$1,
69850         osmNode: osmNode,
69851         osmRelation: osmRelation,
69852         osmWay: osmWay,
69853         osmIntersection: osmIntersection,
69854         osmTurn: osmTurn,
69855         osmInferRestriction: osmInferRestriction,
69856         osmLanes: osmLanes,
69857         osmIsSimpleMultipolygonOuterMember: osmIsSimpleMultipolygonOuterMember,
69858         osmSimpleMultipolygonOuterMember: osmSimpleMultipolygonOuterMember,
69859         osmJoinWays: osmJoinWays,
69860         osmOneWayTags: osmOneWayTags,
69861         osmPavedTags: osmPavedTags,
69862         osmIsInterestingTag: osmIsInterestingTag,
69863         presetCategory: presetCategory,
69864         presetCollection: presetCollection,
69865         presetField: presetField,
69866         presetPreset: presetPreset,
69867         presetIndex: presetIndex,
69868         rendererBackgroundSource: rendererBackgroundSource,
69869         rendererBackground: rendererBackground,
69870         rendererFeatures: rendererFeatures,
69871         rendererMap: rendererMap,
69872         rendererTileLayer: rendererTileLayer,
69873         services: services,
69874         svgAreas: svgAreas$$1,
69875         svgDebug: svgDebug,
69876         svgDefs: svgDefs,
69877         svgGpx: svgGpx,
69878         svgIcon: svgIcon,
69879         svgLabels: svgLabels,
69880         svgLayers: svgLayers,
69881         svgLines: svgLines$$1,
69882         svgMapillaryImages: svgMapillaryImages,
69883         svgMapillarySigns: svgMapillarySigns,
69884         svgMidpoints: svgMidpoints$$1,
69885         svgOneWaySegments: svgOneWaySegments,
69886         svgOsm: svgOsm,
69887         svgPath: svgPath,
69888         svgPointTransform: svgPointTransform,
69889         svgPoints: svgPoints$$1,
69890         svgRelationMemberTags: svgRelationMemberTags,
69891         svgTagClasses: svgTagClasses,
69892         svgTurns: svgTurns,
69893         svgVertices: svgVertices$$1,
69894         uiFields: uiFields,
69895         uiFieldDefaultcheck: uiFieldCheck,
69896         uiFieldCheck: uiFieldCheck,
69897         uiFieldTypeCombo: uiFieldCombo,
69898         uiFieldMultiCombo: uiFieldCombo,
69899         uiFieldNetworkCombo: uiFieldCombo,
69900         uiFieldCombo: uiFieldCombo,
69901         uiFieldUrl: uiFieldText,
69902         uiFieldNumber: uiFieldText,
69903         uiFieldTel: uiFieldText,
69904         uiFieldEmail: uiFieldText,
69905         uiFieldText: uiFieldText,
69906         uiFieldAccess: uiFieldAccess,
69907         uiFieldAddress: uiFieldAddress,
69908         uiFieldCycleway: uiFieldCycleway,
69909         uiFieldLanes: uiFieldLanes,
69910         uiFieldLocalized: uiFieldLocalized,
69911         uiFieldMaxspeed: uiFieldMaxspeed,
69912         uiFieldRadio: uiFieldRadio,
69913         uiFieldRestrictions: uiFieldRestrictions,
69914         uiFieldTextarea: uiFieldTextarea,
69915         uiFieldWikipedia: uiFieldWikipedia,
69916         uiIntro: uiIntro,
69917         uiInit: uiInit,
69918         uiAccount: uiAccount,
69919         uiAttribution: uiAttribution,
69920         uiBackground: uiBackground,
69921         uiCmd: uiCmd,
69922         uiCommit: uiCommit,
69923         uiConfirm: uiConfirm,
69924         uiConflicts: uiConflicts,
69925         uiContributors: uiContributors,
69926         uiDisclosure: uiDisclosure,
69927         uiEntityEditor: uiEntityEditor,
69928         uiFeatureInfo: uiFeatureInfo,
69929         uiFeatureList: uiFeatureList,
69930         uiFlash: uiFlash,
69931         uiFullScreen: uiFullScreen,
69932         uiGeolocate: uiGeolocate,
69933         uiHelp: uiHelp,
69934         uiInfo: uiInfo,
69935         uiInspector: uiInspector,
69936         uiLasso: uiLasso,
69937         uiLoading: uiLoading,
69938         uiMapData: uiMapData,
69939         uiMapInMap: uiMapInMap,
69940         uiModal: uiModal,
69941         uiModes: uiModes,
69942         uiNotice: uiNotice,
69943         uiPreset: uiPreset,
69944         uiPresetIcon: uiPresetIcon,
69945         uiPresetList: uiPresetList,
69946         uiRadialMenu: uiRadialMenu,
69947         uiRawMemberEditor: uiRawMemberEditor,
69948         uiRawMembershipEditor: uiRawMembershipEditor,
69949         uiRawTagEditor: uiRawTagEditor,
69950         uiRestore: uiRestore,
69951         uiSave: uiSave,
69952         uiScale: uiScale,
69953         uiSelectionList: uiSelectionList,
69954         uiSidebar: uiSidebar,
69955         uiSourceSwitch: uiSourceSwitch,
69956         uiSpinner: uiSpinner,
69957         uiSplash: uiSplash,
69958         uiStatus: uiStatus,
69959         uiSuccess: uiSuccess,
69960         uiTagReference: uiTagReference,
69961         uiToggle: uiToggle,
69962         uiTooltipHtml: uiTooltipHtml,
69963         uiUndoRedo: uiUndoRedo,
69964         uiViewOnOSM: uiViewOnOSM,
69965         uiZoom: uiZoom,
69966         utilTagText: utilTagText,
69967         utilEntitySelector: utilEntitySelector,
69968         utilEntityOrMemberSelector: utilEntityOrMemberSelector,
69969         utilDisplayName: utilDisplayName,
69970         utilDisplayType: utilDisplayType,
69971         utilStringQs: utilStringQs,
69972         utilQsString: utilQsString,
69973         utilPrefixDOMProperty: utilPrefixDOMProperty,
69974         utilPrefixCSSProperty: utilPrefixCSSProperty,
69975         utilSetTransform: utilSetTransform,
69976         utilEditDistance: utilEditDistance,
69977         utilFastMouse: utilFastMouse,
69978         utilGetPrototypeOf: utilGetPrototypeOf,
69979         utilAsyncMap: utilAsyncMap,
69980         utilWrap: utilWrap,
69981         utilFunctor: utilFunctor,
69982         utilSessionMutex: utilSessionMutex,
69983         utilSuggestNames: utilSuggestNames,
69984         utilTriggerEvent: utilTriggerEvent,
69985         utilGetSetValue: utilGetSetValue,
69986         d3combobox: d3combobox,
69987         d3geoTile: d3geoTile,
69988         d3keybinding: d3keybinding,
69989         validationDeprecatedTag: validationDeprecatedTag,
69990         validationManyDeletions: validationManyDeletions,
69991         validationMissingTag: validationMissingTag,
69992         validationTagSuggestsArea: validationTagSuggestsArea
69993 });
69994
69995 window.iD = iD;
69996
69997 }());
69998 //# sourceMappingURL=iD.js.map